-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[GlobalISel][ARM] Legalze set_fpenv and get_fpenv #79852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Implement handling of get/set floating point environment for ARM in Global Instruction Selector. Lowering of these intrinsics to operations on FPSCR was previously inplemented in DAG selector, in GlobalISel it is reused.
@llvm/pr-subscribers-backend-arm @llvm/pr-subscribers-llvm-globalisel Author: Serge Pavlov (spavloff) ChangesImplement handling of get/set floating point environment for ARM in Global Instruction Selector. Lowering of these intrinsics to operations on FPSCR was previously inplemented in DAG selector, in GlobalISel it is reused. Full diff: https://github.com/llvm/llvm-project/pull/79852.diff 3 Files Affected:
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index abea0fef5cdc5f3..7bf44abf3fa8f12 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -193,6 +193,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
.legalForCartesianProduct({s32}, {s32, s64});
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalForCartesianProduct({s32, s64}, {s32});
+
+ getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV})
+ .legalFor({s32});
+ getActionDefinitionsBuilder(G_RESET_FPENV)
+ .legalIf([=](const LegalityQuery &Query) { return true; });
} else {
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
.libcallFor({s32, s64});
@@ -219,6 +224,9 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
.libcallForCartesianProduct({s32}, {s32, s64});
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.libcallForCartesianProduct({s32, s64}, {s32});
+
+ getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV})
+ .libcall();
}
// Just expand whatever loads and stores are left.
diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
index 746a8715df0a652..5d4ae9a7648e694 100644
--- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
@@ -469,6 +469,14 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
OperandsMapping = getOperandsMapping(OperandBanks);
break;
}
+ case G_GET_FPENV:
+ case G_SET_FPENV:
+ OperandsMapping =
+ getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
+ break;
+ case G_RESET_FPENV:
+ OperandsMapping = getOperandsMapping({nullptr});
+ break;
default:
return getInvalidInstructionMapping();
}
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll b/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
new file mode 100644
index 000000000000000..3d18a65bd434523
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll
@@ -0,0 +1,78 @@
+; 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
+; CHECK-NEXT: vmrs r0, fpscr
+; CHECK-NEXT: mov pc, lr
+entry:
+ %fpenv = call i32 @llvm.get.fpenv.i32()
+ ret i32 %fpenv
+}
+
+define i32 @func_get_fpenv_soft() #0 {
+; CHECK-LABEL: func_get_fpenv_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 fegetenv
+; 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.fpenv.i32()
+ ret i32 %fpenv
+}
+
+define void @func_set_fpenv(i32 %fpenv) {
+; CHECK-LABEL: func_set_fpenv:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: vmsr fpscr, r0
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.set.fpenv.i32(i32 %fpenv)
+ ret void
+}
+
+define void @func_set_fpenv_soft(i32 %fpenv) #0 {
+; CHECK-LABEL: func_set_fpenv_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 fesetenv
+; CHECK-NEXT: add sp, sp, #8
+; CHECK-NEXT: pop {r11, lr}
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.set.fpenv.i32(i32 %fpenv)
+ ret void
+}
+
+define void @func_reset() {
+; CHECK-LABEL: func_reset:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: mov r0, #0
+; CHECK-NEXT: vmsr fpscr, r0
+; CHECK-NEXT: mov pc, lr
+entry:
+ call void @llvm.reset.fpenv()
+ ret void
+}
+
+attributes #0 = { nounwind "use-soft-float"="true" }
+
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV}) | ||
.legalFor({s32}); | ||
getActionDefinitionsBuilder(G_RESET_FPENV) | ||
.legalIf([=](const LegalityQuery &Query) { return true; }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.alwaysLegal();
Implement handling of get/set floating point environment for ARM in Global Instruction Selector. Lowering of these intrinsics to operations on FPSCR was previously inplemented in DAG selector, in GlobalISel it is reused.
Implement handling of get/set floating point environment for ARM in Global Instruction Selector. Lowering of these intrinsics to operations on FPSCR was previously inplemented in DAG selector, in GlobalISel it is reused.