Skip to content

Commit ebaa56f

Browse files
committed
[GlobalISel] Lowering of {get,set,reset}_fpenv
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 f7f7574 commit ebaa56f

File tree

10 files changed

+230
-0
lines changed

10 files changed

+230
-0
lines changed

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 3 additions & 0 deletions
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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,8 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
18441844
return TargetOpcode::G_LROUND;
18451845
case Intrinsic::llround:
18461846
return TargetOpcode::G_LLROUND;
1847+
case Intrinsic::get_fpenv:
1848+
return TargetOpcode::G_GET_FPENV;
18471849
case Intrinsic::get_fpmode:
18481850
return TargetOpcode::G_GET_FPMODE;
18491851
}
@@ -2427,6 +2429,16 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
24272429

24282430
return true;
24292431
}
2432+
case Intrinsic::set_fpenv: {
2433+
Value *FPEnv = CI.getOperand(0);
2434+
MIRBuilder.buildInstr(TargetOpcode::G_SET_FPENV, {},
2435+
{ getOrCreateVReg(*FPEnv) });
2436+
return true;
2437+
}
2438+
case Intrinsic::reset_fpenv: {
2439+
MIRBuilder.buildInstr(TargetOpcode::G_RESET_FPENV, {}, {});
2440+
return true;
2441+
}
24302442
case Intrinsic::set_fpmode: {
24312443
Value *FPState = CI.getOperand(0);
24322444
MIRBuilder.buildInstr(TargetOpcode::G_SET_FPMODE, {},

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 10 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
11651165
getActionDefinitionsBuilder(G_FMAD).lower();
11661166

11671167
// Access to floating-point environment.
1168+
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV})
1169+
.libcall();
11681170
getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
11691171
.libcall();
11701172

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

Lines changed: 37 additions & 0 deletions
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:
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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+
target triple = "aarch64-unknown-linux-gnu"
6+
7+
declare i64 @llvm.get.fpenv.i64()
8+
declare void @llvm.set.fpenv.i64(i64)
9+
declare void @llvm.reset.fpenv()
10+
11+
define i64 @func_get_fpenv() {
12+
entry:
13+
%fpenv = call i64 @llvm.get.fpenv.i64()
14+
ret i64 %fpenv
15+
}
16+
17+
define void @func_set_fpenv(i64 %fpenv) {
18+
entry:
19+
call void @llvm.set.fpenv.i64(i64 %fpenv)
20+
ret void
21+
}
22+
23+
define void @func_reset() {
24+
entry:
25+
call void @llvm.reset.fpenv()
26+
ret void
27+
}
28+
29+
...
30+
---
31+
name: func_get_fpenv
32+
tracksRegLiveness: true
33+
body: |
34+
bb.1.entry:
35+
; CHECK-LABEL: name: func_get_fpenv
36+
; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
37+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
38+
; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
39+
; CHECK-NEXT: BL &fegetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
40+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
41+
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %stack.0)
42+
; CHECK-NEXT: $x0 = COPY [[LOAD]](s64)
43+
; CHECK-NEXT: RET_ReallyLR implicit $x0
44+
%0:_(s64) = G_GET_FPENV
45+
$x0 = COPY %0(s64)
46+
RET_ReallyLR implicit $x0
47+
48+
...
49+
---
50+
name: func_set_fpenv
51+
tracksRegLiveness: true
52+
body: |
53+
bb.1.entry:
54+
liveins: $x0
55+
56+
; CHECK-LABEL: name: func_set_fpenv
57+
; CHECK: liveins: $x0
58+
; CHECK-NEXT: {{ $}}
59+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
60+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
61+
; CHECK-NEXT: G_STORE [[COPY]](s64), [[FRAME_INDEX]](p0) :: (store (s64) into %stack.0)
62+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
63+
; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
64+
; CHECK-NEXT: BL &fesetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
65+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
66+
; CHECK-NEXT: RET_ReallyLR
67+
%0:_(s64) = COPY $x0
68+
G_SET_FPENV %0(s64)
69+
RET_ReallyLR
70+
71+
...
72+
---
73+
name: func_reset
74+
tracksRegLiveness: true
75+
body: |
76+
bb.1.entry:
77+
; CHECK-LABEL: name: func_reset
78+
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
79+
; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[C]](s64)
80+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
81+
; CHECK-NEXT: $x0 = COPY [[INTTOPTR]](p0)
82+
; CHECK-NEXT: BL &fesetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
83+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
84+
; CHECK-NEXT: RET_ReallyLR
85+
G_RESET_FPENV
86+
RET_ReallyLR
87+
88+
...

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,17 @@
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 196): 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 197): 1 type index, 0 imm indices
560+
# DEBUG-NEXT: .. opcode 197 is aliased to 196
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 198): 0 type indices, 0 imm indices
564+
# DEBUG-NEXT: .. opcode 198 is aliased to 196
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
557568
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
558569
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected

llvm/test/CodeGen/AArch64/fpenv.ll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,47 @@ define void @func_set_rounding_downward() {
6262
ret void
6363
}
6464

65+
define i64 @get_fpenv_01() nounwind {
66+
; CHECK-LABEL: get_fpenv_01:
67+
; CHECK: // %bb.0: // %entry
68+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
69+
; CHECK-NEXT: add x0, sp, #8
70+
; CHECK-NEXT: bl fegetenv
71+
; CHECK-NEXT: ldr x0, [sp, #8]
72+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
73+
; CHECK-NEXT: ret
74+
entry:
75+
%fpenv = call i64 @llvm.get.fpenv.i64()
76+
ret i64 %fpenv
77+
}
78+
79+
define void @set_fpenv_01(i64 %fpenv) nounwind {
80+
; CHECK-LABEL: set_fpenv_01:
81+
; CHECK: // %bb.0: // %entry
82+
; CHECK-NEXT: stp x30, x0, [sp, #-16]! // 8-byte Folded Spill
83+
; CHECK-NEXT: add x0, sp, #8
84+
; CHECK-NEXT: bl fesetenv
85+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
86+
; CHECK-NEXT: ret
87+
entry:
88+
call void @llvm.set.fpenv.i64(i64 %fpenv)
89+
ret void
90+
}
91+
92+
define void @reset_fpenv_01() nounwind {
93+
; CHECK-LABEL: reset_fpenv_01:
94+
; CHECK: // %bb.0: // %entry
95+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
96+
; CHECK-NEXT: mov x0, #-1 // =0xffffffffffffffff
97+
; CHECK-NEXT: bl fesetenv
98+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
99+
; CHECK-NEXT: ret
100+
entry:
101+
call void @llvm.reset.fpenv()
102+
ret void
103+
}
104+
65105
declare void @llvm.set.rounding(i32)
106+
declare i64 @llvm.get.fpenv.i64()
107+
declare void @llvm.set.fpenv.i64(i64 %fpenv)
108+
declare void @llvm.reset.fpenv()

0 commit comments

Comments
 (0)