[llvm] [InstCombine] Drop Range attribute when simplifying 'fshl' based on demanded bits (PR #124429)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 25 12:25:27 PST 2025
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/124429
When simplifying operands based on demanded bits, the return value range
of llvm.fshl might change. Keeping the Range attribute might cause
llvm.fshl to generate a poison and lead to miscompile (#124387). Drop the Range
attribute similar to `dropPosonGeneratingFlags` elsewhere.
>From 942bd381db30d2938407f6ad79991d5408ada73e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 25 Jan 2025 11:55:52 -0800
Subject: [PATCH 1/2] [InstCombine] Test incorrect retention of fshl range
---
llvm/test/Transforms/InstCombine/fsh.ll | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 236c69e7a5bcb7..34648d586300f0 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1068,3 +1068,18 @@ entry:
%res = call <2 x i31> @llvm.fshl.v2i31(<2 x i31> %x, <2 x i31> zeroinitializer, <2 x i31> %y)
ret <2 x i31> %res
}
+
+define i8 @fshl_range_trunc(i1 %x) {
+; CHECK-LABEL: @fshl_range_trunc(
+; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[X:%.*]] to i32
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[ZEXT]], 126
+; CHECK-NEXT: [[FSHL:%.*]] = call range(i32 -4, 2) i32 @llvm.fshl.i32(i32 [[OR]], i32 -2, i32 1)
+; CHECK-NEXT: [[TR:%.*]] = trunc nuw i32 [[FSHL]] to i8
+; CHECK-NEXT: ret i8 [[TR]]
+;
+ %zext = zext i1 %x to i32
+ %or = or disjoint i32 %zext, -2
+ %fshl = call range(i32 -4, 2) i32 @llvm.fshl.i32(i32 %or, i32 %or, i32 1)
+ %tr = trunc nsw i32 %fshl to i8
+ ret i8 %tr
+}
>From 20a3e4d2e12a8fff78623aea248bd607165a7a1e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 25 Jan 2025 11:58:20 -0800
Subject: [PATCH 2/2] [InstCombine] Drop Range attribute when simplifying
'fshl' based on demanded bits
When simplifying operands based on demanded bits, the return value range
of llvm.fshl might change. Keeping the Range attribute might cause
llvm.fshl to generate a poison and lead to miscompile (#124387). Drop the Range
attribute similar to `dropPosonGeneratingFlags` elsewhere.
---
.../InstCombine/InstCombineSimplifyDemanded.cpp | 9 ++++++---
llvm/test/Transforms/InstCombine/fsh.ll | 2 +-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 943598a30f040f..1b89839a72b94b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1039,11 +1039,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
APInt DemandedMaskLHS(DemandedMask.lshr(ShiftAmt));
APInt DemandedMaskRHS(DemandedMask.shl(BitWidth - ShiftAmt));
if (I->getOperand(0) != I->getOperand(1)) {
- if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown,
- Depth + 1, Q) ||
+ if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown, Depth + 1,
+ Q) ||
SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Depth + 1,
- Q))
+ Q)) {
+ // Range attribute may not longer hold.
+ I->dropPoisonGeneratingReturnAttributes();
return I;
+ }
} else { // fshl is a rotate
// Avoid converting rotate into funnel shift.
// Only simplify if one operand is constant.
diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 34648d586300f0..e52e8af5f65ca6 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1073,7 +1073,7 @@ define i8 @fshl_range_trunc(i1 %x) {
; CHECK-LABEL: @fshl_range_trunc(
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[X:%.*]] to i32
; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[ZEXT]], 126
-; CHECK-NEXT: [[FSHL:%.*]] = call range(i32 -4, 2) i32 @llvm.fshl.i32(i32 [[OR]], i32 -2, i32 1)
+; CHECK-NEXT: [[FSHL:%.*]] = call i32 @llvm.fshl.i32(i32 [[OR]], i32 -2, i32 1)
; CHECK-NEXT: [[TR:%.*]] = trunc nuw i32 [[FSHL]] to i8
; CHECK-NEXT: ret i8 [[TR]]
;
More information about the llvm-commits
mailing list