Skip to content

Commit 7fc7ef1

Browse files
authored
[GlobalISel] Lowering of {get,set,reset}_fpenv (#75086)
The intrinsics get_fpenv, set_fpenv and reset_fpenv in this change are implemented as calls to math library functions. Target specific lowering will be implemented later on.
1 parent 7388b74 commit 7fc7ef1

File tree

11 files changed

+203
-2
lines changed

11 files changed

+203
-2
lines changed

llvm/include/llvm/Support/TargetOpcodes.def

+3
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,9 @@ HANDLE_TARGET_OPCODE(G_FMINIMUM)
687687
HANDLE_TARGET_OPCODE(G_FMAXIMUM)
688688

689689
/// Access to FP environment.
690+
HANDLE_TARGET_OPCODE(G_GET_FPENV)
691+
HANDLE_TARGET_OPCODE(G_SET_FPENV)
692+
HANDLE_TARGET_OPCODE(G_RESET_FPENV)
690693
HANDLE_TARGET_OPCODE(G_GET_FPMODE)
691694
HANDLE_TARGET_OPCODE(G_SET_FPMODE)
692695
HANDLE_TARGET_OPCODE(G_RESET_FPMODE)

llvm/include/llvm/Target/GenericOpcodes.td

+21
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,27 @@ def G_FNEARBYINT : GenericInstruction {
10201020
// it is modeled as a side effect, because constrained intrinsics use the same
10211021
// method.
10221022

1023+
// Reading floating-point environment.
1024+
def G_GET_FPENV : GenericInstruction {
1025+
let OutOperandList = (outs type0:$dst);
1026+
let InOperandList = (ins);
1027+
let hasSideEffects = true;
1028+
}
1029+
1030+
// Setting floating-point environment.
1031+
def G_SET_FPENV : GenericInstruction {
1032+
let OutOperandList = (outs);
1033+
let InOperandList = (ins type0:$src);
1034+
let hasSideEffects = true;
1035+
}
1036+
1037+
// Setting default floating-point environment.
1038+
def G_RESET_FPENV : GenericInstruction {
1039+
let OutOperandList = (outs);
1040+
let InOperandList = (ins);
1041+
let hasSideEffects = true;
1042+
}
1043+
10231044
// Reading floating-point control modes.
10241045
def G_GET_FPMODE : GenericInstruction {
10251046
let OutOperandList = (outs type0:$dst);

llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td

+3
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain> {
116116
let IfConvergent = G_INTRINSIC_CONVERGENT;
117117
}
118118

119+
def : GINodeEquiv<G_GET_FPENV, get_fpenv>;
120+
def : GINodeEquiv<G_SET_FPENV, set_fpenv>;
121+
def : GINodeEquiv<G_RESET_FPENV, reset_fpenv>;
119122
def : GINodeEquiv<G_GET_FPMODE, get_fpmode>;
120123
def : GINodeEquiv<G_SET_FPMODE, set_fpmode>;
121124
def : GINodeEquiv<G_RESET_FPMODE, reset_fpmode>;

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,8 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
19191919
return TargetOpcode::G_LROUND;
19201920
case Intrinsic::llround:
19211921
return TargetOpcode::G_LLROUND;
1922+
case Intrinsic::get_fpenv:
1923+
return TargetOpcode::G_GET_FPENV;
19221924
case Intrinsic::get_fpmode:
19231925
return TargetOpcode::G_GET_FPMODE;
19241926
}
@@ -2502,6 +2504,16 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
25022504

25032505
return true;
25042506
}
2507+
case Intrinsic::set_fpenv: {
2508+
Value *FPEnv = CI.getOperand(0);
2509+
MIRBuilder.buildInstr(TargetOpcode::G_SET_FPENV, {},
2510+
{getOrCreateVReg(*FPEnv)});
2511+
return true;
2512+
}
2513+
case Intrinsic::reset_fpenv: {
2514+
MIRBuilder.buildInstr(TargetOpcode::G_RESET_FPENV, {}, {});
2515+
return true;
2516+
}
25052517
case Intrinsic::set_fpmode: {
25062518
Value *FPState = CI.getOperand(0);
25072519
MIRBuilder.buildInstr(TargetOpcode::G_SET_FPMODE, {},

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,13 @@ static RTLIB::Libcall
958958
getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI) {
959959
RTLIB::Libcall RTLibcall;
960960
switch (MI.getOpcode()) {
961+
case TargetOpcode::G_GET_FPENV:
962+
RTLibcall = RTLIB::FEGETENV;
963+
break;
964+
case TargetOpcode::G_SET_FPENV:
965+
case TargetOpcode::G_RESET_FPENV:
966+
RTLibcall = RTLIB::FESETENV;
967+
break;
961968
case TargetOpcode::G_GET_FPMODE:
962969
RTLibcall = RTLIB::FEGETMODE;
963970
break;
@@ -1232,18 +1239,21 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
12321239
MI.eraseFromParent();
12331240
return Result;
12341241
}
1242+
case TargetOpcode::G_GET_FPENV:
12351243
case TargetOpcode::G_GET_FPMODE: {
12361244
LegalizeResult Result = createGetStateLibcall(MIRBuilder, MI, LocObserver);
12371245
if (Result != Legalized)
12381246
return Result;
12391247
break;
12401248
}
1249+
case TargetOpcode::G_SET_FPENV:
12411250
case TargetOpcode::G_SET_FPMODE: {
12421251
LegalizeResult Result = createSetStateLibcall(MIRBuilder, MI, LocObserver);
12431252
if (Result != Legalized)
12441253
return Result;
12451254
break;
12461255
}
1256+
case TargetOpcode::G_RESET_FPENV:
12471257
case TargetOpcode::G_RESET_FPMODE: {
12481258
LegalizeResult Result =
12491259
createResetStateLibcall(MIRBuilder, MI, LocObserver);

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1166,7 +1166,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
11661166
getActionDefinitionsBuilder(G_FMAD).lower();
11671167

11681168
// Access to floating-point environment.
1169-
getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
1169+
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV,
1170+
G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
11701171
.libcall();
11711172

11721173
getActionDefinitionsBuilder(G_IS_FPCLASS).lower();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2+
; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -global-isel -global-isel-abort=1 %s -o - | FileCheck %s
3+
4+
declare i64 @llvm.get.fpenv.i64()
5+
declare void @llvm.set.fpenv.i64(i64 %fpenv)
6+
declare void @llvm.reset.fpenv()
7+
8+
define i64 @get_fpenv_01() nounwind {
9+
; CHECK-LABEL: get_fpenv_01:
10+
; CHECK: // %bb.0: // %entry
11+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
12+
; CHECK-NEXT: add x0, sp, #8
13+
; CHECK-NEXT: bl fegetenv
14+
; CHECK-NEXT: ldr x0, [sp, #8]
15+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
16+
; CHECK-NEXT: ret
17+
entry:
18+
%fpenv = call i64 @llvm.get.fpenv.i64()
19+
ret i64 %fpenv
20+
}
21+
22+
define void @set_fpenv_01(i64 %fpenv) nounwind {
23+
; CHECK-LABEL: set_fpenv_01:
24+
; CHECK: // %bb.0: // %entry
25+
; CHECK-NEXT: stp x30, x0, [sp, #-16]! // 8-byte Folded Spill
26+
; CHECK-NEXT: add x0, sp, #8
27+
; CHECK-NEXT: bl fesetenv
28+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
29+
; CHECK-NEXT: ret
30+
entry:
31+
call void @llvm.set.fpenv.i64(i64 %fpenv)
32+
ret void
33+
}
34+
35+
define void @reset_fpenv_01() nounwind {
36+
; CHECK-LABEL: reset_fpenv_01:
37+
; CHECK: // %bb.0: // %entry
38+
; CHECK-NEXT: mov x0, #-1 // =0xffffffffffffffff
39+
; CHECK-NEXT: b fesetenv
40+
entry:
41+
call void @llvm.reset.fpenv()
42+
ret void
43+
}

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll

+37
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
11
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
22
; RUN: llc -O0 -mtriple=aarch64-linux-gnu -global-isel -stop-after=irtranslator %s -o - | FileCheck %s
33

4+
declare i64 @llvm.get.fpenv.i64()
5+
declare void @llvm.set.fpenv.i64(i64 %fpenv)
6+
declare void @llvm.reset.fpenv()
47
declare i32 @llvm.get.fpmode.i32()
58
declare void @llvm.set.fpmode.i32(i32 %fpmode)
69
declare void @llvm.reset.fpmode()
710

11+
define i64 @func_get_fpenv() #0 {
12+
; CHECK-LABEL: name: func_get_fpenv
13+
; CHECK: bb.1.entry:
14+
; CHECK-NEXT: [[GET_FPENV:%[0-9]+]]:_(s64) = G_GET_FPENV
15+
; CHECK-NEXT: $x0 = COPY [[GET_FPENV]](s64)
16+
; CHECK-NEXT: RET_ReallyLR implicit $x0
17+
entry:
18+
%fpenv = call i64 @llvm.get.fpenv.i64()
19+
ret i64 %fpenv
20+
}
21+
22+
define void @func_set_fpenv(i64 %fpenv) #0 {
23+
; CHECK-LABEL: name: func_set_fpenv
24+
; CHECK: bb.1.entry:
25+
; CHECK-NEXT: liveins: $x0
26+
; CHECK-NEXT: {{ $}}
27+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
28+
; CHECK-NEXT: G_SET_FPENV [[COPY]](s64)
29+
; CHECK-NEXT: RET_ReallyLR
30+
entry:
31+
call void @llvm.set.fpenv.i64(i64 %fpenv)
32+
ret void
33+
}
34+
35+
define void @func_reset_fpenv() #0 {
36+
; CHECK-LABEL: name: func_reset_fpenv
37+
; CHECK: bb.1.entry:
38+
; CHECK-NEXT: G_RESET_FPENV
39+
; CHECK-NEXT: RET_ReallyLR
40+
entry:
41+
call void @llvm.reset.fpenv()
42+
ret void
43+
}
44+
845
define i32 @func_get_fpmode() #0 {
946
; CHECK-LABEL: name: func_get_fpmode
1047
; CHECK: bb.1.entry:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
2+
# RUN: llc -mtriple=aarch64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s
3+
4+
---
5+
name: func_get_fpenv
6+
tracksRegLiveness: true
7+
body: |
8+
bb.0:
9+
; CHECK-LABEL: name: func_get_fpenv
10+
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
11+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
12+
; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
13+
; CHECK-NEXT: BL &fegetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
14+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
15+
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %stack.0)
16+
; CHECK-NEXT: $x0 = COPY [[LOAD]](s64)
17+
; CHECK-NEXT: RET_ReallyLR implicit $x0
18+
%0:_(s64) = G_GET_FPENV
19+
$x0 = COPY %0(s64)
20+
RET_ReallyLR implicit $x0
21+
22+
...
23+
---
24+
name: func_set_fpenv
25+
tracksRegLiveness: true
26+
body: |
27+
bb.0:
28+
liveins: $x0
29+
30+
; CHECK-LABEL: name: func_set_fpenv
31+
; CHECK: liveins: $x0
32+
; CHECK-NEXT: {{ $}}
33+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
34+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
35+
; CHECK-NEXT: G_STORE [[COPY]](s64), [[FRAME_INDEX]](p0) :: (store (s64) into %stack.0)
36+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
37+
; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
38+
; CHECK-NEXT: BL &fesetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
39+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
40+
; CHECK-NEXT: RET_ReallyLR
41+
%0:_(s64) = COPY $x0
42+
G_SET_FPENV %0(s64)
43+
RET_ReallyLR
44+
45+
...
46+
---
47+
name: func_reset
48+
tracksRegLiveness: true
49+
body: |
50+
bb.0:
51+
; CHECK-LABEL: name: func_reset
52+
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
53+
; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[C]](s64)
54+
; CHECK-NEXT: $x0 = COPY [[INTTOPTR]](p0)
55+
; CHECK-NEXT: TCRETURNdi &fesetenv, 0, csr_aarch64_aapcs, implicit $sp, implicit $x0
56+
G_RESET_FPENV
57+
RET_ReallyLR
58+
59+
...

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

+12
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,19 @@
553553
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
554554
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
555555
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
556+
# DEBUG-NEXT: G_GET_FPENV (opcode {{[0-9]+}}): 1 type index, 0 imm indices
557+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
558+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
559+
# DEBUG-NEXT: G_SET_FPENV (opcode {{[0-9]+}}): 1 type index, 0 imm indices
560+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
561+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
562+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
563+
# DEBUG-NEXT: G_RESET_FPENV (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
564+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
565+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
566+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
556567
# DEBUG-NEXT: G_GET_FPMODE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
568+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
557569
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
558570
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
559571
# DEBUG-NEXT: G_SET_FPMODE (opcode {{[0-9]+}}): 1 type index, 0 imm indices

llvm/test/TableGen/GlobalISelEmitter.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
518518
// R00O-NEXT: GIM_Reject,
519519
// R00O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
520520
// R00O-NEXT: GIM_Reject,
521-
// R00O-NEXT: }; // Size: 2007 bytes
521+
// R00O-NEXT: }; // Size: 2019 bytes
522522

523523
def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
524524
[(set GPR32:$dst,

0 commit comments

Comments
 (0)