Skip to content

Commit f850d8a

Browse files
spavloffAlexisPerry
authored andcommitted
[GlobalISel][ARM] Legalze set_fpmode and get_fpmode (llvm#96467)
Implement handling of get/set floating point control modes for ARM in Global Instruction Selector.
1 parent 895a392 commit f850d8a

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

llvm/lib/Target/ARM/ARMLegalizerInfo.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,10 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
157157
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
158158
.legalForCartesianProduct({s32, s64}, {s32});
159159

160-
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV}).legalFor({s32});
160+
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_GET_FPMODE})
161+
.legalFor({s32});
161162
getActionDefinitionsBuilder(G_RESET_FPENV).alwaysLegal();
163+
getActionDefinitionsBuilder(G_SET_FPMODE).customFor({s32});
162164
} else {
163165
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
164166
.libcallFor({s32, s64});
@@ -187,6 +189,8 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
187189

188190
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV})
189191
.libcall();
192+
getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
193+
.libcall();
190194
}
191195

192196
// Just expand whatever loads and stores are left.
@@ -439,6 +443,21 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
439443
*ConstantInt::get(Ctx, AsInteger));
440444
break;
441445
}
446+
case G_SET_FPMODE: {
447+
// New FPSCR = (FPSCR & FPStatusBits) | (Modes & ~FPStatusBits)
448+
LLT FPEnvTy = LLT::scalar(32);
449+
auto FPEnv = MRI.createGenericVirtualRegister(FPEnvTy);
450+
Register Modes = MI.getOperand(0).getReg();
451+
MIRBuilder.buildGetFPEnv(FPEnv);
452+
auto StatusBitMask = MIRBuilder.buildConstant(FPEnvTy, ARM::FPStatusBits);
453+
auto StatusBits = MIRBuilder.buildAnd(FPEnvTy, FPEnv, StatusBitMask);
454+
auto NotStatusBitMask =
455+
MIRBuilder.buildConstant(FPEnvTy, ~ARM::FPStatusBits);
456+
auto FPModeBits = MIRBuilder.buildAnd(FPEnvTy, Modes, NotStatusBitMask);
457+
auto NewFPSCR = MIRBuilder.buildOr(FPEnvTy, StatusBits, FPModeBits);
458+
MIRBuilder.buildSetFPEnv(NewFPSCR);
459+
break;
460+
}
442461
}
443462

444463
MI.eraseFromParent();

llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
466466
}
467467
case G_GET_FPENV:
468468
case G_SET_FPENV:
469+
case G_GET_FPMODE:
469470
OperandsMapping =
470471
getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
471472
break;

llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
22
; RUN: llc -mtriple=arm-eabi -mattr=+vfp2 -global-isel=1 --verify-machineinstrs %s -o - | FileCheck %s
33

4-
declare i32 @llvm.get.fpenv.i32()
5-
declare void @llvm.set.fpenv.i32(i32)
6-
declare void @llvm.reset.fpenv()
7-
84
define i32 @func_get_fpenv() {
95
; CHECK-LABEL: func_get_fpenv:
106
; CHECK: @ %bb.0: @ %entry
@@ -88,5 +84,86 @@ entry:
8884
ret void
8985
}
9086

87+
88+
define i32 @get_fpmode_soft() #0 {
89+
; CHECK-LABEL: get_fpmode_soft:
90+
; CHECK: @ %bb.0: @ %entry
91+
; CHECK-NEXT: .save {r4, lr}
92+
; CHECK-NEXT: push {r4, lr}
93+
; CHECK-NEXT: .pad #8
94+
; CHECK-NEXT: sub sp, sp, #8
95+
; CHECK-NEXT: add r4, sp, #4
96+
; CHECK-NEXT: mov r0, r4
97+
; CHECK-NEXT: bl fegetmode
98+
; CHECK-NEXT: ldr r0, [r4]
99+
; CHECK-NEXT: add sp, sp, #8
100+
; CHECK-NEXT: pop {r4, lr}
101+
; CHECK-NEXT: mov pc, lr
102+
entry:
103+
%fpenv = call i32 @llvm.get.fpmode.i32()
104+
ret i32 %fpenv
105+
}
106+
107+
define i32 @get_fpmode() nounwind {
108+
; CHECK-LABEL: get_fpmode:
109+
; CHECK: @ %bb.0: @ %entry
110+
; CHECK-NEXT: vmrs r0, fpscr
111+
; CHECK-NEXT: mov pc, lr
112+
entry:
113+
%fpenv = call i32 @llvm.get.fpmode.i32()
114+
ret i32 %fpenv
115+
}
116+
117+
define void @set_fpmode_soft(i32 %fpmode) #0 {
118+
; CHECK-LABEL: set_fpmode_soft:
119+
; CHECK: @ %bb.0: @ %entry
120+
; CHECK-NEXT: .save {r11, lr}
121+
; CHECK-NEXT: push {r11, lr}
122+
; CHECK-NEXT: .pad #8
123+
; CHECK-NEXT: sub sp, sp, #8
124+
; CHECK-NEXT: add r1, sp, #4
125+
; CHECK-NEXT: str r0, [r1]
126+
; CHECK-NEXT: mov r0, r1
127+
; CHECK-NEXT: bl fesetmode
128+
; CHECK-NEXT: add sp, sp, #8
129+
; CHECK-NEXT: pop {r11, lr}
130+
; CHECK-NEXT: mov pc, lr
131+
entry:
132+
call void @llvm.set.fpmode.i32(i32 %fpmode)
133+
ret void
134+
}
135+
136+
define void @set_fpmode(i32 %fpmode) nounwind {
137+
; CHECK-LABEL: set_fpmode:
138+
; CHECK: @ %bb.0: @ %entry
139+
; CHECK-NEXT: vmrs r1, fpscr
140+
; CHECK-NEXT: mov r2, #159
141+
; CHECK-NEXT: orr r2, r2, #-134217728
142+
; CHECK-NEXT: and r1, r1, r2
143+
; CHECK-NEXT: mvn r2, #159
144+
; CHECK-NEXT: sub r2, r2, #-134217728
145+
; CHECK-NEXT: and r0, r0, r2
146+
; CHECK-NEXT: orr r0, r1, r0
147+
; CHECK-NEXT: vmsr fpscr, r0
148+
; CHECK-NEXT: mov pc, lr
149+
entry:
150+
call void @llvm.set.fpmode.i32(i32 %fpmode)
151+
ret void
152+
}
153+
154+
define void @reset_fpmode_soft() #0 {
155+
; CHECK-LABEL: reset_fpmode_soft:
156+
; CHECK: @ %bb.0: @ %entry
157+
; CHECK-NEXT: .save {r11, lr}
158+
; CHECK-NEXT: push {r11, lr}
159+
; CHECK-NEXT: mvn r0, #0
160+
; CHECK-NEXT: bl fesetmode
161+
; CHECK-NEXT: pop {r11, lr}
162+
; CHECK-NEXT: mov pc, lr
163+
entry:
164+
call void @llvm.reset.fpmode()
165+
ret void
166+
}
167+
91168
attributes #0 = { nounwind "use-soft-float"="true" }
92169

0 commit comments

Comments
 (0)