[llvm] 67c9a6c - [InstCombine] Drop poison-generating annotations when rewriting rotate operands (#224228)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 03:10:51 PDT 2026


Author: Chennes
Date: 2026-09-17T10:10:45Z
New Revision: 67c9a6cbf0b5cd78d2223342ec9f07c903b559e1

URL: https://github.com/llvm/llvm-project/commit/67c9a6cbf0b5cd78d2223342ec9f07c903b559e1
DIFF: https://github.com/llvm/llvm-project/commit/67c9a6cbf0b5cd78d2223342ec9f07c903b559e1.diff

LOG: [InstCombine] Drop poison-generating annotations when rewriting rotate operands (#224228)

`SimplifyDemandedUseBits()` rewrites an operand of a rotate to the
constant formed from its known bits, which preserves only the demanded
bits of the result. A `range` attribute or `!range` metadata on the call
may no longer hold afterwards, turning a defined result into poison:
https://alive2.llvm.org/ce/z/Lk8Eop

#173864 extended annotation dropping in the funnel shift path directly
above to cover metadata; the rotate path never had it.

Drop the annotations in both rotate operand rewrite paths.

Fixes #222092.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
    llvm/test/Transforms/InstCombine/fsh.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 34a2da3bf03f2..7d35907e96bea 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1134,6 +1134,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
           if (DemandedMaskLHS.isSubsetOf(LHSKnown.Zero | LHSKnown.One) &&
               !match(I->getOperand(0), m_SpecificInt(LHSKnown.One))) {
             replaceOperand(*I, 0, Constant::getIntegerValue(VTy, LHSKnown.One));
+            // Range attribute or metadata may no longer hold.
+            I->dropPoisonGeneratingAnnotations();
             return I;
           }
 
@@ -1141,6 +1143,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
           if (DemandedMaskRHS.isSubsetOf(RHSKnown.Zero | RHSKnown.One) &&
               !match(I->getOperand(1), m_SpecificInt(RHSKnown.One))) {
             replaceOperand(*I, 1, Constant::getIntegerValue(VTy, RHSKnown.One));
+            // Range attribute or metadata may no longer hold.
+            I->dropPoisonGeneratingAnnotations();
             return I;
           }
         }

diff  --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 453d12be4375f..4ced6099792ac 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1,6 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
+declare i8 @llvm.fshl.i8(i8, i8, i8)
 declare i16 @llvm.fshl.i16(i16, i16, i16)
 declare i16 @llvm.fshr.i16(i16, i16, i16)
 declare i32 @llvm.fshl.i32(i32, i32, i32)
@@ -1171,6 +1172,38 @@ define <2 x i8> @fshl_range_vec(<2 x i1> %x) {
   ret <2 x i8> %tr
 }
 
+;; Issue #222092 Range attribute no longer holds after a rotate operand is
+;; rewritten.
+
+; The other operand is a load, which the revisit cannot simplify further. For a
+; loaded value of 26 the rotate returns 52, which is in [50, 56), while
+; rewriting the LHS to its known bits (24) returns 48, which is not.
+define i8 @fshl_rotate_range_attr_lhs(ptr %p) {
+; CHECK-LABEL: @fshl_rotate_range_attr_lhs(
+; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[P:%.*]], align 1, !range [[RNG0:![0-9]+]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 24, i8 [[X]], i8 1)
+; CHECK-NEXT:    [[M:%.*]] = and i8 [[R]], 17
+; CHECK-NEXT:    ret i8 [[M]]
+;
+  %x = load i8, ptr %p, align 1, !range !{i8 -104, i8 -100, i8 24, i8 28}
+  %r = call range(i8 50, 56) i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 1)
+  %m = and i8 %r, 17
+  ret i8 %m
+}
+
+; The other operand is a bare argument. For x = 48 the rotate returns 3, which
+; is in [3, 64), while rewriting the RHS to its known bits (32) returns 2.
+define i8 @fshl_rotate_range_attr_rhs(i8 range(i8 32, 64) %x) {
+; CHECK-LABEL: @fshl_rotate_range_attr_rhs(
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 32, i8 4)
+; CHECK-NEXT:    [[M:%.*]] = and i8 [[R]], 50
+; CHECK-NEXT:    ret i8 [[M]]
+;
+  %r = call range(i8 3, 64) i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 4)
+  %m = and i8 %r, 50
+  ret i8 %m
+}
+
 ;; Issue #138334 negative rotate amounts can be folded into the opposite direction
 define i32 @fshl_neg_amount(i32 %x, i32 %y) {
 ; CHECK-LABEL: @fshl_neg_amount(


        


More information about the llvm-commits mailing list