Skip to content
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

[GlobalISel][ARM] Legalze set_fpenv and get_fpenv #79852

Merged
merged 3 commits into from
Feb 4, 2024

Conversation

spavloff
Copy link
Collaborator

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.
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 29, 2024

@llvm/pr-subscribers-backend-arm

@llvm/pr-subscribers-llvm-globalisel

Author: Serge Pavlov (spavloff)

Changes

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 --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" }
+

Copy link

github-actions bot commented Jan 29, 2024

✅ 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; });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.alwaysLegal();

@spavloff spavloff merged commit b4eb7a1 into llvm:main Feb 4, 2024
3 of 4 checks passed
@spavloff spavloff deleted the arm.getenv branch February 4, 2024 05:30
agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants