Skip to content

[GlobalISel] Lowering of {get,set,reset}_fpenv #75086

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

Merged
merged 7 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1844,6 +1844,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;
}
Expand Down Expand Up @@ -2427,6 +2429,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, {},
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,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();
Expand Down
43 changes: 43 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/fpenv.ll
Original file line number Diff line number Diff line change
@@ -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
}
37 changes: 37 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fpenv.ll
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
59 changes: 59 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalize-fpenv.mir
Original file line number Diff line number Diff line change
@@ -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

...
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/TableGen/GlobalISelEmitter.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down