[llvm] 4c9b71d - [GlobalISel][ARM] Legalze set_fpmode and get_fpmode (#96467)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 26 05:41:47 PDT 2024
Author: Serge Pavlov
Date: 2024-06-26T19:41:44+07:00
New Revision: 4c9b71dd9171164efbb99de5e75d4fcadf0e21b5
URL: https://github.com/llvm/llvm-project/commit/4c9b71dd9171164efbb99de5e75d4fcadf0e21b5
DIFF: https://github.com/llvm/llvm-project/commit/4c9b71dd9171164efbb99de5e75d4fcadf0e21b5.diff
LOG: [GlobalISel][ARM] Legalze set_fpmode and get_fpmode (#96467)
Implement handling of get/set floating point control modes for ARM in
Global Instruction Selector.
Added:
Modified:
llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index 00a29f8ecb232..660f351bae64b 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -157,8 +157,10 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalForCartesianProduct({s32, s64}, {s32});
- getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV}).legalFor({s32});
+ getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_GET_FPMODE})
+ .legalFor({s32});
getActionDefinitionsBuilder(G_RESET_FPENV).alwaysLegal();
+ getActionDefinitionsBuilder(G_SET_FPMODE).customFor({s32});
} else {
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
.libcallFor({s32, s64});
@@ -187,6 +189,8 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV})
.libcall();
+ getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
+ .libcall();
}
// Just expand whatever loads and stores are left.
@@ -439,6 +443,21 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
*ConstantInt::get(Ctx, AsInteger));
break;
}
+ case G_SET_FPMODE: {
+ // New FPSCR = (FPSCR & FPStatusBits) | (Modes & ~FPStatusBits)
+ LLT FPEnvTy = LLT::scalar(32);
+ auto FPEnv = MRI.createGenericVirtualRegister(FPEnvTy);
+ Register Modes = MI.getOperand(0).getReg();
+ MIRBuilder.buildGetFPEnv(FPEnv);
+ auto StatusBitMask = MIRBuilder.buildConstant(FPEnvTy, ARM::FPStatusBits);
+ auto StatusBits = MIRBuilder.buildAnd(FPEnvTy, FPEnv, StatusBitMask);
+ auto NotStatusBitMask =
+ MIRBuilder.buildConstant(FPEnvTy, ~ARM::FPStatusBits);
+ auto FPModeBits = MIRBuilder.buildAnd(FPEnvTy, Modes, NotStatusBitMask);
+ auto NewFPSCR = MIRBuilder.buildOr(FPEnvTy, StatusBits, FPModeBits);
+ MIRBuilder.buildSetFPEnv(NewFPSCR);
+ break;
+ }
}
MI.eraseFromParent();
diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
index a6fdece10ba47..9234881c9407e 100644
--- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
@@ -466,6 +466,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
}
case G_GET_FPENV:
case G_SET_FPENV:
+ case G_GET_FPMODE:
OperandsMapping =
getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
break;
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll b/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
index f5aea62d4be79..f8dba64e7a01a 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
+++ b/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
@@ -1,10 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=arm-eabi -mattr=+vfp2 -global-isel=1 --verify-machineinstrs %s -o - | FileCheck %s
-declare i32 @llvm.get.fpenv.i32()
-declare void @llvm.set.fpenv.i32(i32)
-declare void @llvm.reset.fpenv()
-
define i32 @func_get_fpenv() {
; CHECK-LABEL: func_get_fpenv:
; CHECK: @ %bb.0: @ %entry
@@ -88,5 +84,86 @@ entry:
ret void
}
+
+define i32 @get_fpmode_soft() #0 {
+; CHECK-LABEL: get_fpmode_soft:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: .save {r4, lr}
+; CHECK-NEXT: push {r4, lr}
+; CHECK-NEXT: .pad #8
+; CHECK-NEXT: sub sp, sp, #8
+; CHECK-NEXT: add r4, sp, #4
+; CHECK-NEXT: mov r0, r4
+; CHECK-NEXT: bl fegetmode
+; CHECK-NEXT: ldr r0, [r4]
+; CHECK-NEXT: add sp, sp, #8
+; CHECK-NEXT: pop {r4, lr}
+; CHECK-NEXT: mov pc, lr
+entry:
+ %fpenv = call i32 @llvm.get.fpmode.i32()
+ ret i32 %fpenv
+}
+
+define i32 @get_fpmode() nounwind {
+; CHECK-LABEL: get_fpmode:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: vmrs r0, fpscr
+; CHECK-NEXT: mov pc, lr
+entry:
+ %fpenv = call i32 @llvm.get.fpmode.i32()
+ ret i32 %fpenv
+}
+
+define void @set_fpmode_soft(i32 %fpmode) #0 {
+; CHECK-LABEL: set_fpmode_soft:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: .save {r11, lr}
+; CHECK-NEXT: push {r11, lr}
+; CHECK-NEXT: .pad #8
+; CHECK-NEXT: sub sp, sp, #8
+; CHECK-NEXT: add r1, sp, #4
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bl fesetmode
+; CHECK-NEXT: add sp, sp, #8
+; CHECK-NEXT: pop {r11, lr}
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.set.fpmode.i32(i32 %fpmode)
+ ret void
+}
+
+define void @set_fpmode(i32 %fpmode) nounwind {
+; CHECK-LABEL: set_fpmode:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: vmrs r1, fpscr
+; CHECK-NEXT: mov r2, #159
+; CHECK-NEXT: orr r2, r2, #-134217728
+; CHECK-NEXT: and r1, r1, r2
+; CHECK-NEXT: mvn r2, #159
+; CHECK-NEXT: sub r2, r2, #-134217728
+; CHECK-NEXT: and r0, r0, r2
+; CHECK-NEXT: orr r0, r1, r0
+; CHECK-NEXT: vmsr fpscr, r0
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.set.fpmode.i32(i32 %fpmode)
+ ret void
+}
+
+define void @reset_fpmode_soft() #0 {
+; CHECK-LABEL: reset_fpmode_soft:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: .save {r11, lr}
+; CHECK-NEXT: push {r11, lr}
+; CHECK-NEXT: mvn r0, #0
+; CHECK-NEXT: bl fesetmode
+; CHECK-NEXT: pop {r11, lr}
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.reset.fpmode()
+ ret void
+}
+
attributes #0 = { nounwind "use-soft-float"="true" }
More information about the llvm-commits
mailing list