-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV][GISel] Support f32/f64 powi. #117937
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
Conversation
Need to force libcall legalization to treat the integer argument as signed so that it can be promoted to XLen in call lowering for RV64. Alternatively we could promote the operand before converting to libcall, but going through call lowering is closer to what SelectionDAG does.
@llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesNeed to force libcall legalization to treat the integer argument as signed so that it can be promoted to XLen in call lowering for RV64. Alternatively we could promote the operand before converting to libcall, but going through call lowering is closer to what SelectionDAG does. Full diff: https://github.com/llvm/llvm-project/pull/117937.diff 4 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 709eb2525a6577..dd424afd0a909f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1290,9 +1290,10 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
return UnableToLegalize;
}
auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
- std::initializer_list<CallLowering::ArgInfo> Args = {
+ SmallVector<CallLowering::ArgInfo, 2> Args = {
{MI.getOperand(1).getReg(), HLTy, 0},
{MI.getOperand(2).getReg(), ITy, 1}};
+ Args[1].Flags[0].setSExt();
LegalizeResult Status =
createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), HLTy, 0},
Args, LocObserver, &MI);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index a4e03be98c696d..005d88a1731232 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,6 +579,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
+ getActionDefinitionsBuilder(G_FPOWI)
+ .libcallFor({{s32, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
index 16b0a2fc2f396d..7098493b2b56d3 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
@@ -48,6 +48,48 @@ define float @sqrt_f32(float %a) nounwind {
ret float %1
}
+define float @powi_f32(float %a, i32 %b) nounwind {
+; RV32IF-LABEL: powi_f32:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: addi sp, sp, -16
+; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IF-NEXT: call __powisf2
+; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: ret
+;
+; RV64IF-LABEL: powi_f32:
+; RV64IF: # %bb.0:
+; RV64IF-NEXT: addi sp, sp, -16
+; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IF-NEXT: sext.w a0, a0
+; RV64IF-NEXT: call __powisf2
+; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IF-NEXT: addi sp, sp, 16
+; RV64IF-NEXT: ret
+;
+; RV32I-LABEL: powi_f32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __powisf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: powi_f32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call __powisf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call float @llvm.powi.f32.i32(float %a, i32 %b)
+ ret float %1
+}
+
define float @sin_f32(float %a) nounwind {
; RV32IF-LABEL: sin_f32:
; RV32IF: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 719ea38cbb9c52..f14c806607c710 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -481,8 +481,8 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FPOWI (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FEXP (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
|
@llvm/pr-subscribers-llvm-globalisel Author: Craig Topper (topperc) ChangesNeed to force libcall legalization to treat the integer argument as signed so that it can be promoted to XLen in call lowering for RV64. Alternatively we could promote the operand before converting to libcall, but going through call lowering is closer to what SelectionDAG does. Full diff: https://github.com/llvm/llvm-project/pull/117937.diff 4 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 709eb2525a6577..dd424afd0a909f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1290,9 +1290,10 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
return UnableToLegalize;
}
auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
- std::initializer_list<CallLowering::ArgInfo> Args = {
+ SmallVector<CallLowering::ArgInfo, 2> Args = {
{MI.getOperand(1).getReg(), HLTy, 0},
{MI.getOperand(2).getReg(), ITy, 1}};
+ Args[1].Flags[0].setSExt();
LegalizeResult Status =
createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), HLTy, 0},
Args, LocObserver, &MI);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index a4e03be98c696d..005d88a1731232 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,6 +579,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
+ getActionDefinitionsBuilder(G_FPOWI)
+ .libcallFor({{s32, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
index 16b0a2fc2f396d..7098493b2b56d3 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
@@ -48,6 +48,48 @@ define float @sqrt_f32(float %a) nounwind {
ret float %1
}
+define float @powi_f32(float %a, i32 %b) nounwind {
+; RV32IF-LABEL: powi_f32:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: addi sp, sp, -16
+; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IF-NEXT: call __powisf2
+; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: ret
+;
+; RV64IF-LABEL: powi_f32:
+; RV64IF: # %bb.0:
+; RV64IF-NEXT: addi sp, sp, -16
+; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IF-NEXT: sext.w a0, a0
+; RV64IF-NEXT: call __powisf2
+; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IF-NEXT: addi sp, sp, 16
+; RV64IF-NEXT: ret
+;
+; RV32I-LABEL: powi_f32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __powisf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: powi_f32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call __powisf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call float @llvm.powi.f32.i32(float %a, i32 %b)
+ ret float %1
+}
+
define float @sin_f32(float %a) nounwind {
; RV32IF-LABEL: sin_f32:
; RV32IF: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 719ea38cbb9c52..f14c806607c710 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -481,8 +481,8 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FPOWI (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FEXP (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
{MI.getOperand(1).getReg(), HLTy, 0}, | ||
{MI.getOperand(2).getReg(), ITy, 1}}; | ||
Args[1].Flags[0].setSExt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, sorry, I'm not 100% sure about this - should we be using things like TargetLowering::shouldSignExtendTypeInLibCall
/TargetLowering::shouldExtendTypeInLibCall
to choose whether to (sign) extend? It's not clear to me we have a GISel equivalent to those callbacks, but I think we might need something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eventually yes we probably need something like those hooks. A signed integer argument is maybe the least interesting case for those hooks.
shouldExtendTypeInLibCall defaults to true and only RISC-V and LoongArch override it to return false for FP types.
shouldSignExtendTypeInLibCall defaults to returning true for signed types and only RISC-V, LoongArch, and Mips override it to return true for some unsigned integers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
{MI.getOperand(1).getReg(), HLTy, 0}, | ||
{MI.getOperand(2).getReg(), ITy, 1}}; | ||
Args[1].Flags[0].setSExt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense
Need to force libcall legalization to treat the integer argument as signed so that it can be promoted to XLen in call lowering for RV64. Alternatively we could promote the operand before converting to libcall, but going through call lowering is closer to what SelectionDAG does.