[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 13:20:13 PST 2025


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/124429

>From 4747d7a9adbfbdf7cfe8ef856fa3d5a6668cc9b4 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] [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. Drop the Range
attribute similar to `dropPosonGeneratingFlags` elsewhere.

Fix #124387
---
 .../InstCombine/InstCombineSimplifyDemanded.cpp          | 9 ++++++---
 llvm/test/Transforms/InstCombine/fsh.ll                  | 3 ++-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 943598a30f040f..2c8939b5a05143 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 no 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..3ff4f9a2abf33e 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1069,11 +1069,12 @@ entry:
   ret <2 x i31>  %res
 }
 
+;; Issue #124387 Range attribute no longer holds after operands changed.
 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