[llvm] 7fc7ef1 - [GlobalISel] Lowering of {get, set, reset}_fpenv (#75086)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 9 23:18:04 PST 2024
Author: Serge Pavlov
Date: 2024-01-10T14:18:00+07:00
New Revision: 7fc7ef14340a3a58cebd0801497b68eb698c2784
URL: https://github.com/llvm/llvm-project/commit/7fc7ef14340a3a58cebd0801497b68eb698c2784
DIFF: https://github.com/llvm/llvm-project/commit/7fc7ef14340a3a58cebd0801497b68eb698c2784.diff
LOG: [GlobalISel] Lowering of {get,set,reset}_fpenv (#75086)
The intrinsics get_fpenv, set_fpenv and reset_fpenv in this change are
implemented as calls to math library functions. Target specific lowering
will be implemented later on.
Added:
llvm/test/CodeGen/AArch64/GlobalISel/fpenv.ll
llvm/test/CodeGen/AArch64/GlobalISel/legalize-fpenv.mir
Modified:
llvm/include/llvm/Support/TargetOpcodes.def
llvm/include/llvm/Target/GenericOpcodes.td
llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll
llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
llvm/test/TableGen/GlobalISelEmitter.td
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 3824b1c66951e8..c005218c80f44a 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -687,6 +687,9 @@ HANDLE_TARGET_OPCODE(G_FMINIMUM)
HANDLE_TARGET_OPCODE(G_FMAXIMUM)
/// Access to FP environment.
+HANDLE_TARGET_OPCODE(G_GET_FPENV)
+HANDLE_TARGET_OPCODE(G_SET_FPENV)
+HANDLE_TARGET_OPCODE(G_RESET_FPENV)
HANDLE_TARGET_OPCODE(G_GET_FPMODE)
HANDLE_TARGET_OPCODE(G_SET_FPMODE)
HANDLE_TARGET_OPCODE(G_RESET_FPMODE)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 73e38b15bf6719..2c73b67f9e1af0 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1020,6 +1020,27 @@ def G_FNEARBYINT : GenericInstruction {
// it is modeled as a side effect, because constrained intrinsics use the same
// method.
+// Reading floating-point environment.
+def G_GET_FPENV : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins);
+ let hasSideEffects = true;
+}
+
+// Setting floating-point environment.
+def G_SET_FPENV : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins type0:$src);
+ let hasSideEffects = true;
+}
+
+// Setting default floating-point environment.
+def G_RESET_FPENV : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins);
+ let hasSideEffects = true;
+}
+
// Reading floating-point control modes.
def G_GET_FPMODE : GenericInstruction {
let OutOperandList = (outs type0:$dst);
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 5e704f0b9a758b..f792237203b431 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -116,6 +116,9 @@ def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain> {
let IfConvergent = G_INTRINSIC_CONVERGENT;
}
+def : GINodeEquiv<G_GET_FPENV, get_fpenv>;
+def : GINodeEquiv<G_SET_FPENV, set_fpenv>;
+def : GINodeEquiv<G_RESET_FPENV, reset_fpenv>;
def : GINodeEquiv<G_GET_FPMODE, get_fpmode>;
def : GINodeEquiv<G_SET_FPMODE, set_fpmode>;
def : GINodeEquiv<G_RESET_FPMODE, reset_fpmode>;
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 6708f2baa5ed5f..8a6bfdc5ee669c 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1919,6 +1919,8 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
return TargetOpcode::G_LROUND;
case Intrinsic::llround:
return TargetOpcode::G_LLROUND;
+ case Intrinsic::get_fpenv:
+ return TargetOpcode::G_GET_FPENV;
case Intrinsic::get_fpmode:
return TargetOpcode::G_GET_FPMODE;
}
@@ -2502,6 +2504,16 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
return true;
}
+ case Intrinsic::set_fpenv: {
+ Value *FPEnv = CI.getOperand(0);
+ MIRBuilder.buildInstr(TargetOpcode::G_SET_FPENV, {},
+ {getOrCreateVReg(*FPEnv)});
+ return true;
+ }
+ case Intrinsic::reset_fpenv: {
+ MIRBuilder.buildInstr(TargetOpcode::G_RESET_FPENV, {}, {});
+ return true;
+ }
case Intrinsic::set_fpmode: {
Value *FPState = CI.getOperand(0);
MIRBuilder.buildInstr(TargetOpcode::G_SET_FPMODE, {},
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index def7f6ebeb011c..21947a55874aa3 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -958,6 +958,13 @@ static RTLIB::Libcall
getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI) {
RTLIB::Libcall RTLibcall;
switch (MI.getOpcode()) {
+ case TargetOpcode::G_GET_FPENV:
+ RTLibcall = RTLIB::FEGETENV;
+ break;
+ case TargetOpcode::G_SET_FPENV:
+ case TargetOpcode::G_RESET_FPENV:
+ RTLibcall = RTLIB::FESETENV;
+ break;
case TargetOpcode::G_GET_FPMODE:
RTLibcall = RTLIB::FEGETMODE;
break;
@@ -1232,18 +1239,21 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
MI.eraseFromParent();
return Result;
}
+ case TargetOpcode::G_GET_FPENV:
case TargetOpcode::G_GET_FPMODE: {
LegalizeResult Result = createGetStateLibcall(MIRBuilder, MI, LocObserver);
if (Result != Legalized)
return Result;
break;
}
+ case TargetOpcode::G_SET_FPENV:
case TargetOpcode::G_SET_FPMODE: {
LegalizeResult Result = createSetStateLibcall(MIRBuilder, MI, LocObserver);
if (Result != Legalized)
return Result;
break;
}
+ case TargetOpcode::G_RESET_FPENV:
case TargetOpcode::G_RESET_FPMODE: {
LegalizeResult Result =
createResetStateLibcall(MIRBuilder, MI, LocObserver);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index b657a0954d7894..302116447efccd 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1166,7 +1166,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
getActionDefinitionsBuilder(G_FMAD).lower();
// Access to floating-point environment.
- getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
+ getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV,
+ G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
.libcall();
getActionDefinitionsBuilder(G_IS_FPCLASS).lower();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/fpenv.ll b/llvm/test/CodeGen/AArch64/GlobalISel/fpenv.ll
new file mode 100644
index 00000000000000..a95d6505183780
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/fpenv.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -global-isel -global-isel-abort=1 %s -o - | FileCheck %s
+
+declare i64 @llvm.get.fpenv.i64()
+declare void @llvm.set.fpenv.i64(i64 %fpenv)
+declare void @llvm.reset.fpenv()
+
+define i64 @get_fpenv_01() nounwind {
+; CHECK-LABEL: get_fpenv_01:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: add x0, sp, #8
+; CHECK-NEXT: bl fegetenv
+; CHECK-NEXT: ldr x0, [sp, #8]
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+entry:
+ %fpenv = call i64 @llvm.get.fpenv.i64()
+ ret i64 %fpenv
+}
+
+define void @set_fpenv_01(i64 %fpenv) nounwind {
+; CHECK-LABEL: set_fpenv_01:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: stp x30, x0, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: add x0, sp, #8
+; CHECK-NEXT: bl fesetenv
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.set.fpenv.i64(i64 %fpenv)
+ ret void
+}
+
+define void @reset_fpenv_01() nounwind {
+; CHECK-LABEL: reset_fpenv_01:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov x0, #-1 // =0xffffffffffffffff
+; CHECK-NEXT: b fesetenv
+entry:
+ call void @llvm.reset.fpenv()
+ ret void
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll
index fda9269d423d05..9a8e5529f0a1e4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll
@@ -1,10 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
; RUN: llc -O0 -mtriple=aarch64-linux-gnu -global-isel -stop-after=irtranslator %s -o - | FileCheck %s
+declare i64 @llvm.get.fpenv.i64()
+declare void @llvm.set.fpenv.i64(i64 %fpenv)
+declare void @llvm.reset.fpenv()
declare i32 @llvm.get.fpmode.i32()
declare void @llvm.set.fpmode.i32(i32 %fpmode)
declare void @llvm.reset.fpmode()
+define i64 @func_get_fpenv() #0 {
+ ; CHECK-LABEL: name: func_get_fpenv
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: [[GET_FPENV:%[0-9]+]]:_(s64) = G_GET_FPENV
+ ; CHECK-NEXT: $x0 = COPY [[GET_FPENV]](s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+entry:
+ %fpenv = call i64 @llvm.get.fpenv.i64()
+ ret i64 %fpenv
+}
+
+define void @func_set_fpenv(i64 %fpenv) #0 {
+ ; CHECK-LABEL: name: func_set_fpenv
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: G_SET_FPENV [[COPY]](s64)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.set.fpenv.i64(i64 %fpenv)
+ ret void
+}
+
+define void @func_reset_fpenv() #0 {
+ ; CHECK-LABEL: name: func_reset_fpenv
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: G_RESET_FPENV
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.reset.fpenv()
+ ret void
+}
+
define i32 @func_get_fpmode() #0 {
; CHECK-LABEL: name: func_get_fpmode
; CHECK: bb.1.entry:
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-fpenv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-fpenv.mir
new file mode 100644
index 00000000000000..936f839280c4d6
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-fpenv.mir
@@ -0,0 +1,59 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
+# RUN: llc -mtriple=aarch64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s
+
+---
+name: func_get_fpenv
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: func_get_fpenv
+ ; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
+ ; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
+ ; CHECK-NEXT: BL &fegetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: $x0 = COPY [[LOAD]](s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %0:_(s64) = G_GET_FPENV
+ $x0 = COPY %0(s64)
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: func_set_fpenv
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: func_set_fpenv
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
+ ; CHECK-NEXT: G_STORE [[COPY]](s64), [[FRAME_INDEX]](p0) :: (store (s64) into %stack.0)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
+ ; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
+ ; CHECK-NEXT: BL &fesetenv, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(s64) = COPY $x0
+ G_SET_FPENV %0(s64)
+ RET_ReallyLR
+
+...
+---
+name: func_reset
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: func_reset
+ ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+ ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[C]](s64)
+ ; CHECK-NEXT: $x0 = COPY [[INTTOPTR]](p0)
+ ; CHECK-NEXT: TCRETURNdi &fesetenv, 0, csr_aarch64_aapcs, implicit $sp, implicit $x0
+ G_RESET_FPENV
+ RET_ReallyLR
+
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 2adf9763a96b65..c90c31aa27ef57 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -553,7 +553,19 @@
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_GET_FPENV (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_SET_FPENV (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_RESET_FPENV (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_GET_FPMODE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_SET_FPMODE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td
index f9d7d2dcccdbb8..dd3ac6cc3672a0 100644
--- a/llvm/test/TableGen/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter.td
@@ -518,7 +518,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
// R00O-NEXT: GIM_Reject,
// R00O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
// R00O-NEXT: GIM_Reject,
-// R00O-NEXT: }; // Size: 2007 bytes
+// R00O-NEXT: }; // Size: 2019 bytes
def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
[(set GPR32:$dst,
More information about the llvm-commits
mailing list