[llvm] [GlobalISel][ARM] Legalze set_fpenv and get_fpenv (PR #79852)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 29 08:03:17 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: Serge Pavlov (spavloff)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/79852.diff
3 Files Affected:
- (modified) llvm/lib/Target/ARM/ARMLegalizerInfo.cpp (+8)
- (modified) llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (+8)
- (added) llvm/test/CodeGen/ARM/GlobalISel/fpenv.ll (+78)
``````````diff
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" }
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/79852
More information about the llvm-commits
mailing list