-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[RISCV][GISel] Do libcall for G_FPTOSI, G_FPTOUI when no D or F support #94613
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
…ns are not supported
@llvm/pr-subscribers-llvm-globalisel @llvm/pr-subscribers-backend-risc-v Author: Gábor Spaits (spaits) ChangesWhen compiling the following code: #include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
int main() {
int a;
float f;
scanf("%d", &a);
scanf("%f", &f);
a += (int)f;
return a;
} for
When we try to use GlobalISel we get this error:
(Here is a link to a reproducer in Godblot: https://godbolt.org/z/f67vEEb41 ) The goal of this PR is to do a libcall for the legalization of Full diff: https://github.com/llvm/llvm-project/pull/94613.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index dbfcab7233bf8..69a139957ff23 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -409,7 +409,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
.legalIf(all(typeInSet(0, {s32, sXLen}), typeIsScalarFPArith(1, ST)))
.widenScalarToNextPow2(0)
- .clampScalar(0, s32, sXLen);
+ .clampScalar(0, s32, sXLen)
+ .libcallFor({s32, s32});
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalIf(all(typeIsScalarFPArith(0, ST), typeInSet(1, {s32, sXLen})))
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-fptoi-rv32-libcall.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-fptoi-rv32-libcall.mir
new file mode 100644
index 0000000000000..b22338d521a46
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-fptoi-rv32-libcall.mir
@@ -0,0 +1,194 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=-d -mattr=-f -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+
+---
+name: fptosi_s1_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptosi_s1_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixsfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s1) = G_FPTOSI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptoui_s1_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptoui_s1_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixunssfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s1) = G_FPTOUI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s1)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptosi_s8_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptosi_s8_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixsfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s8) = G_FPTOSI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s8)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptoui_s8_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptoui_s8_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixunssfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s8) = G_FPTOUI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s8)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptosi_s16_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptosi_s16_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixsfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s16) = G_FPTOSI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s16)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptoui_s16_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptoui_s16_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixunssfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s16) = G_FPTOUI %0(s32)
+ %2:_(s32) = G_ANYEXT %1(s16)
+ $x10 = COPY %2(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptosi_s32_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptosi_s32_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixsfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s32) = G_FPTOSI %0(s32)
+ $x10 = COPY %1(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: fptoui_s32_s32
+body: |
+ bb.1:
+ liveins: $f10_f
+
+ ; CHECK-LABEL: name: fptoui_s32_s32
+ ; CHECK: liveins: $f10_f
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $f10_f
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) &__fixunssfsi, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit-def $x10
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
+ ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32)
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:_(s32) = COPY $f10_f
+ %1:_(s32) = G_FPTOUI %0(s32)
+ $x10 = COPY %1(s32)
+ PseudoRET implicit $x10
+
+...
|
llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-fptoi-rv32-libcall.mir
Show resolved
Hide resolved
✅ With the latest revision this PR passed the C/C++ code formatter. |
@@ -17,6 +17,7 @@ | |||
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" | |||
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" | |||
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" | |||
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" |
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.
Why do we need a new include?
@@ -169,7 +170,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) | |||
MergeUnmergeActions.legalIf( | |||
all(typeIs(BigTyIdx, s64), typeIs(LitTyIdx, s32))); | |||
} | |||
MergeUnmergeActions.widenScalarToNextPow2(LitTyIdx, XLen) | |||
MergeUnmergeActions.legalIf(all(typeIs(BigTyIdx, sDoubleXLen), typeIs(LitTyIdx, sXLen))) |
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.
How do we isel this UNMERGE?
; CHECK-NOFLOAT-LABEL: name: fptosi_s1_s64 | ||
; CHECK-NOFLOAT: liveins: $f10_d | ||
; CHECK-NOFLOAT-NEXT: {{ $}} | ||
; CHECK-NOFLOAT-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $f10_d |
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.
Something is broken here. We're passing f10_d, but we don't have floating point?
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.
So f10_d is a register only available when D and F are enabled. So I should be using for example x10 as a livein register right?
This also mean that I will have to use a different file for these tests.
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.
For rv32, you would need to use x10 and x11 to hold all 64 bits. I recommend writing an IR test and using -stop-before=legalizer to get the MIR
@topperc I have updated the PR. I have discovered, that I could move the test for the libcall cases into the same file in which the non-libcall test are with the help of file check. When running the tests fail in some cases with this:
So it says that we have an illegal unmerge that can not be legalized. This does not makes sense to me. I was editing the test for merge a few hours back today and I think this should be legalized by the current rules. I have then realized, that when we are not on an rv32 system that has D extension we never have a This is the commit, that introduced that if that made the How should I proceed with this PR? Why is there no legal I would really appreciate your help. |
d389266
to
669868b
Compare
@topperc I have removed the Could you please re-review this PR? |
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
…rt (llvm#94613) When compiling the following code: ```cpp #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <stdbool.h> int main() { int a; float f; scanf("%d", &a); scanf("%f", &f); a += (int)f; return a; } ``` for `-march=rv32ima_zbb` we get a libcall: ``` call scanf lw a0, -20(s0) call __fixsfsi mv a1, a0 ``` When we try to use GlobalISel we get this error: ``` error in backend: unable to legalize instruction: %9:_(s32) = G_FPTOSI %8:_(s32) (in function: main) ``` (Here is a link to a reproducer in Godblot: https://godbolt.org/z/f67vEEb41 ) The goal of this PR is to do a libcall for the legalization of `G_FPTOSI` and `G_FPTOUI` instead of doing a fallback to Selection DAG to do the same libcall later. Signed-off-by: Hafidz Muzakky <[email protected]>
When compiling the following code:
for
-march=rv32ima_zbb
we get a libcall:When we try to use GlobalISel we get this error:
(Here is a link to a reproducer in Godblot: https://godbolt.org/z/f67vEEb41 )
The goal of this PR is to do a libcall for the legalization of
G_FPTOSI
andG_FPTOUI
instead of doing a fallback to Selection DAG to do the same libcall later.