[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