-
Notifications
You must be signed in to change notification settings - Fork 12k
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
[Float2Int] Resolve FIXME: Pick the smallest legal type that fits #79158
Conversation
@llvm/pr-subscribers-llvm-transforms Author: AtariDreams (AtariDreams) ChangesPick the type based on the smallest bitwidth possible Full diff: https://github.com/llvm/llvm-project/pull/79158.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp
index ccca8bcc1a56ac7..108ad297ce7519e 100644
--- a/llvm/lib/Transforms/Scalar/Float2Int.cpp
+++ b/llvm/lib/Transforms/Scalar/Float2Int.cpp
@@ -383,8 +383,16 @@ bool Float2IntPass::validateAndTransform() {
}
// OK, R is known to be representable. Now pick a type for it.
- // FIXME: Pick the smallest legal type that will fit.
- Type *Ty = (MinBW > 32) ? Type::getInt64Ty(*Ctx) : Type::getInt32Ty(*Ctx);
+ Type *Ty;
+ if (MinBW <= 8) {
+ Ty = Type::getInt8Ty(*Ctx);
+ } else if (MinBW <= 16) {
+ Ty = Type::getInt16Ty(*Ctx);
+ } else if (MinBW <= 32) {
+ Ty = Type::getInt32Ty(*Ctx);
+ } else {
+ Ty = Type::getInt64Ty(*Ctx);
+ }
for (auto MI = ECs.member_begin(It), ME = ECs.member_end();
MI != ME; ++MI)
diff --git a/llvm/test/Transforms/Float2Int/basic.ll b/llvm/test/Transforms/Float2Int/basic.ll
index 2854a83179b7eb6..aa9ef36e4caaab1 100644
--- a/llvm/test/Transforms/Float2Int/basic.ll
+++ b/llvm/test/Transforms/Float2Int/basic.ll
@@ -7,10 +7,9 @@
define i16 @simple1(i8 %a) {
; CHECK-LABEL: @simple1(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16
-; CHECK-NEXT: ret i16 [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 1
+; CHECK-NEXT: ret i16 [[T21]]
;
%t1 = uitofp i8 %a to float
%t2 = fadd float %t1, 1.0
@@ -20,9 +19,9 @@ define i16 @simple1(i8 %a) {
define i8 @simple2(i8 %a) {
; CHECK-LABEL: @simple2(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i16 [[T21]] to i8
; CHECK-NEXT: ret i8 [[TMP2]]
;
%t1 = uitofp i8 %a to float
@@ -33,9 +32,10 @@ define i8 @simple2(i8 %a) {
define i32 @simple3(i8 %a) {
; CHECK-LABEL: @simple3(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1
-; CHECK-NEXT: ret i32 [[T21]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[T21]] to i32
+; CHECK-NEXT: ret i32 [[TMP2]]
;
%t1 = uitofp i8 %a to float
%t2 = fsub float %t1, 1.0
@@ -45,9 +45,9 @@ define i32 @simple3(i8 %a) {
define i1 @cmp(i8 %a, i8 %b) {
; CHECK-LABEL: @cmp(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
-; CHECK-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16
+; CHECK-NEXT: [[T31:%.*]] = icmp slt i16 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i1 [[T31]]
;
%t1 = uitofp i8 %a to float
@@ -106,13 +106,14 @@ define i32 @simple6(i8 %a, i8 %b) {
define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
; CHECK-LABEL: @multi1(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16
; CHECK-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float
-; CHECK-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[X1:%.*]] = add i16 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[X1]] to i32
; CHECK-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]]
; CHECK-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32
-; CHECK-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]]
+; CHECK-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]]
; CHECK-NEXT: ret i32 [[R]]
;
%fa = uitofp i8 %a to float
@@ -128,10 +129,9 @@ define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
define i16 @simple_negzero(i8 %a) {
; CHECK-LABEL: @simple_negzero(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0
-; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16
-; CHECK-NEXT: ret i16 [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 0
+; CHECK-NEXT: ret i16 [[T21]]
;
%t1 = uitofp i8 %a to float
%t2 = fadd fast float %t1, -0.0
@@ -141,9 +141,9 @@ define i16 @simple_negzero(i8 %a) {
define i32 @simple_negative(i8 %call) {
; CHECK-LABEL: @simple_negative(
-; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32
-; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3
-; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8
+; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i16
+; CHECK-NEXT: [[MUL1:%.*]] = mul i16 [[TMP1]], -3
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i16 [[MUL1]] to i8
; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[CONV3]]
;
@@ -156,10 +156,9 @@ define i32 @simple_negative(i8 %call) {
define i16 @simple_fneg(i8 %a) {
; CHECK-LABEL: @simple_fneg(
-; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]]
-; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16
-; CHECK-NEXT: ret i16 [[TMP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[T21:%.*]] = sub i16 0, [[TMP1]]
+; CHECK-NEXT: ret i16 [[T21]]
;
%t1 = uitofp i8 %a to float
%t2 = fneg fast float %t1
|
590d9f6
to
0f671c9
Compare
1b1021d
to
aef840a
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
80a9b71
to
4d74e6d
Compare
4175133
to
b238489
Compare
@nikic Fixed! |
ea8d0a5
to
6d156a2
Compare
I was able to reproduce the difference before and after the revert of the return value being different edit: on x86-64 with |
Oddly enough, the pass itself doesn't seem to be the issue. |
The -passes=float2int one I mean |
PR: only running float2int pass |
Does anyone have a full list of passes that I can try to see is the culprit? |
As far as clang is concerned, you can use LLVM options Apart from that, the |
Sad but true: this is a usual situation, when a seemingly correct change in one pass uncovers issues in one or more of the following passes in the pipeline. This may feel like playing pick up sticks at times, but we see this regularly =( |
Well most passes are pretty uninteresting if you run them on pre-SROA/mem2reg IR. Looking at the later godbolt link, there's the following transform for Float2IntPass: Before:
After:
This is why you've received feedback about these kinds of small changes being awkward to review. When they don't offer significant gains, they are often outweighed by the high risk that something will break, whether that's because the change in question is incorrect or because it exposes incorrect code elsewhere. |
At a glance it looks like confusion about whether or not there's a sign bit. |
This seems to be a preexisting issue that you can hit if you pick specific float values: https://godbolt.org/z/rxdqrve3d It's just hit more often now because you're picking smaller integers. Before you had to be in the range [2^31, 2^32), converted to a double, but now it's true for [2^7, 2^8) and [2^15, 2^16), both of which also fit in a single-precision float, unlike the prior case. |
Compiler Explorer shows this bug as being reproducible with that exact test case all the way back to Clang 3.7 (but not 3.6). Given Float2Int was new in 3.7 (at least from GitHub's view of available tags) that strongly suggests to me this bug has always been there since it was added to the tree (or at least the final attempt at adding it to the tree). |
I found a bug in the ConstantRange handling UIToFP and SIToFP handling which may explain the failure #86041 |
We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason #79158 was reverted.
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted. (cherry picked from commit 1283646)
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
…fits" (llvm#85843) Reverts llvm#79158, which causes a miscompile. See llvm#79158 (comment)
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted.
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted. (cherry picked from commit 1283646)
…m#86041) We were passing the min and max values of the range to the ConstantRange constructor, but the constructor expects the upper bound to 1 more than the max value so we need to add 1. We also need to use getNonEmpty so that passing 0, 0 to the constructor creates a full range rather than an empty range. And passing smin, smax+1 doesn't cause an assertion. I believe this fixes at least some of the reason llvm#79158 was reverted. (cherry picked from commit 1283646)
Pick the type based on the smallest bit-width possible, using DataLayout.