[llvm] [InstCombine] Don't infer exact from an operand that may be undef (PR #218861)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 01:31:56 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Chennes (Chennesxu)

<details>
<summary>Changes</summary>

`setShiftFlags()` infers `exact` for `shr (shl X, Y), Y` and `shr X, cttz(X)` from repeated uses of the same SSA value. That is unsound if the shared value may be `undef`, because each use may observe a different value. As the [LangRef](https://llvm.org/docs/LangRef.html#undefined-values) notes:

> To ensure all uses of a given register observe the same value (even if `undef`), the `freeze` instruction can be used.

Adding `exact` can therefore make the target poison where the source is defined. Alive2 for the reported case: https://alive2.llvm.org/ce/z/Lr_kDN

Require the shared operand to be known not `undef`. The `cttz` rule has the same root cause in the same function and uses the same guard. Its test makes `X` known nonzero, excluding `cttz(0)` as a source of poison and isolating the per-use `undef` issue: https://alive2.llvm.org/ce/z/gXBebC

Concrete constant operands are known not `undef`, so the matching idioms in the Clang, MLIR, and Polly tests are unaffected, and the existing KnownBits fallback still infers `exact` when it proves that all shifted-out bits are zero. The updated checks all use variable shared operands that are not known `noundef`.

Tests cover both rules with `noundef` and frozen shared operands, where the flag is retained, and with undef-derived in-range operands, where it is dropped.

Fixes #<!-- -->217234

---

Patch is 38.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218861.diff


16 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp (+5-2) 
- (modified) llvm/test/Transforms/InstCombine/canonicalize-shl-lshr-to-masking.ll (+1-1) 
- (modified) llvm/test/Transforms/InstCombine/cttz-shift-exact.ll (+41-2) 
- (modified) llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-after-truncation-variant-e.ll (+3-3) 
- (modified) llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-variant-e.ll (+1-1) 
- (modified) llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-e.ll (+5-5) 
- (modified) llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-f.ll (+6-6) 
- (modified) llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-e.ll (+17-13) 
- (modified) llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-f.ll (+18-14) 
- (modified) llvm/test/Transforms/InstCombine/redundant-right-shift-input-masking.ll (+4-4) 
- (modified) llvm/test/Transforms/InstCombine/select.ll (+1-1) 
- (modified) llvm/test/Transforms/InstCombine/sext.ll (+1-1) 
- (modified) llvm/test/Transforms/InstCombine/shift-by-signext.ll (+2-2) 
- (modified) llvm/test/Transforms/InstCombine/shift-flags.ll (+54) 
- (modified) llvm/test/Transforms/InstCombine/variable-signext-of-variable-high-bit-extraction.ll (+6-6) 
- (modified) llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll (+4-4) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 7e32abcd6e9ba..c22633f64306b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1100,13 +1100,16 @@ static bool setShiftFlags(BinaryOperator &I, const SimplifyQuery &Q) {
       return false;
 
     // shr (shl X, Y), Y
-    if (match(I.getOperand(0), m_Shl(m_Value(), m_Specific(I.getOperand(1))))) {
+    // Y must not be undef, as its uses could observe different values.
+    if (match(I.getOperand(0), m_Shl(m_Value(), m_Specific(I.getOperand(1)))) &&
+        isGuaranteedNotToBeUndef(I.getOperand(1), Q.AC, Q.CxtI, Q.DT)) {
       I.setIsExact();
       return true;
     }
     // Infer 'exact' flag if shift amount is cttz(x) on the same operand.
     if (match(I.getOperand(1),
-              m_Cttz(m_Specific(I.getOperand(0)), m_Value()))) {
+              m_Cttz(m_Specific(I.getOperand(0)), m_Value())) &&
+        isGuaranteedNotToBeUndef(I.getOperand(0), Q.AC, Q.CxtI, Q.DT)) {
       I.setIsExact();
       return true;
     }
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-shl-lshr-to-masking.ll b/llvm/test/Transforms/InstCombine/canonicalize-shl-lshr-to-masking.ll
index 400d911929b99..82a6475fa30b9 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-shl-lshr-to-masking.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-shl-lshr-to-masking.ll
@@ -388,7 +388,7 @@ define i32 @negative_oneuse(i32 %x, i32 %y) {
 ; CHECK-LABEL: @negative_oneuse(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
-; CHECK-NEXT:    [[RET:%.*]] = lshr exact i32 [[T0]], [[Y]]
+; CHECK-NEXT:    [[RET:%.*]] = lshr i32 [[T0]], [[Y]]
 ; CHECK-NEXT:    ret i32 [[RET]]
 ;
   %t0 = shl i32 %x, %y
diff --git a/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll b/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
index ee2f7757e4266..be3a73fe760bd 100644
--- a/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
+++ b/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
@@ -7,7 +7,7 @@ define i32 @test_cttz_lshr(i32 %x) {
 ; CHECK-LABEL: define i32 @test_cttz_lshr(
 ; CHECK-SAME: i32 [[X:%.*]]) {
 ; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
-; CHECK-NEXT:    [[SH:%.*]] = lshr exact i32 [[X]], [[CTTZ]]
+; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[X]], [[CTTZ]]
 ; CHECK-NEXT:    ret i32 [[SH]]
 ;
   %cttz = call i32 @llvm.cttz.i32(i32 %x, i1 false)
@@ -19,7 +19,7 @@ define i32 @test_cttz_ashr(i32 %x) {
 ; CHECK-LABEL: define i32 @test_cttz_ashr(
 ; CHECK-SAME: i32 [[X:%.*]]) {
 ; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
-; CHECK-NEXT:    [[SH:%.*]] = ashr exact i32 [[X]], [[CTTZ]]
+; CHECK-NEXT:    [[SH:%.*]] = ashr i32 [[X]], [[CTTZ]]
 ; CHECK-NEXT:    ret i32 [[SH]]
 ;
   %cttz = call i32 @llvm.cttz.i32(i32 %x, i1 true)
@@ -39,3 +39,42 @@ define i32 @test_cttz_diff_operand(i32 %x, i32 %y) {
   ret i32 %sh
 }
 
+define i32 @test_cttz_lshr_noundef(i32 noundef %x) {
+; CHECK-LABEL: define i32 @test_cttz_lshr_noundef(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT:    [[SH:%.*]] = lshr exact i32 [[X]], [[CTTZ]]
+; CHECK-NEXT:    ret i32 [[SH]]
+;
+  %cttz = call i32 @llvm.cttz.i32(i32 %x, i1 false)
+  %sh = lshr i32 %x, %cttz
+  ret i32 %sh
+}
+
+define i32 @test_cttz_ashr_freeze(i32 %x_in) {
+; CHECK-LABEL: define i32 @test_cttz_ashr_freeze(
+; CHECK-SAME: i32 [[X_IN:%.*]]) {
+; CHECK-NEXT:    [[X:%.*]] = freeze i32 [[X_IN]]
+; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT:    [[SH:%.*]] = ashr exact i32 [[X]], [[CTTZ]]
+; CHECK-NEXT:    ret i32 [[SH]]
+;
+  %x = freeze i32 %x_in
+  %cttz = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %sh = ashr i32 %x, %cttz
+  ret i32 %sh
+}
+
+define i32 @test_cttz_lshr_nonzero(i32 %y) {
+; CHECK-LABEL: define i32 @test_cttz_lshr_nonzero(
+; CHECK-SAME: i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[X:%.*]] = or i32 [[Y]], 4
+; CHECK-NEXT:    [[CTTZ:%.*]] = call range(i32 0, 3) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[X]], [[CTTZ]]
+; CHECK-NEXT:    ret i32 [[SH]]
+;
+  %x = or i32 %y, 4
+  %cttz = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %sh = lshr i32 %x, %cttz
+  ret i32 %sh
+}
diff --git a/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-after-truncation-variant-e.ll b/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-after-truncation-variant-e.ll
index 5dda49b280e19..456aaac7c954f 100644
--- a/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-after-truncation-variant-e.ll
+++ b/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-after-truncation-variant-e.ll
@@ -137,7 +137,7 @@ define i32 @n4_extrause0(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T3]])
 ; CHECK-NEXT:    [[T4:%.*]] = trunc i64 [[T3]] to i32
 ; CHECK-NEXT:    [[T5:%.*]] = shl i32 [[T4]], [[T2]]
@@ -166,7 +166,7 @@ define i32 @n5_extrause1(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    [[T4:%.*]] = trunc i64 [[T3]] to i32
 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
 ; CHECK-NEXT:    [[T5:%.*]] = shl i32 [[T4]], [[T2]]
@@ -195,7 +195,7 @@ define i32 @n6_extrause2(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T3]])
 ; CHECK-NEXT:    [[T4:%.*]] = trunc i64 [[T3]] to i32
 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
diff --git a/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-variant-e.ll b/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-variant-e.ll
index 66a46aeb908b5..35e495eaf4266 100644
--- a/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-variant-e.ll
+++ b/llvm/test/Transforms/InstCombine/partally-redundant-left-shift-input-masking-variant-e.ll
@@ -98,7 +98,7 @@ define <8 x i32> @t1_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {
 define i32 @n3_extrause(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @n3_extrause(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -1
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
diff --git a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-e.ll b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-e.ll
index 699e11dcf0358..cbba21b254144 100644
--- a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-e.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-e.ll
@@ -19,7 +19,7 @@ define i32 @t0_basic(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64
 ; CHECK-NEXT:    [[T1:%.*]] = shl i64 [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -32
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
@@ -53,7 +53,7 @@ define <8 x i32> @t1_vec_splat(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], splat (i32 -32)
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -82,7 +82,7 @@ define <8 x i32> @t2_vec_splat_undef(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -32, i32 -32, i32 -32, i32 -32, i32 -32, i32 undef, i32 -32>
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -111,7 +111,7 @@ define <8 x i32> @t3_vec_nonsplat(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 undef, i32 64>
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -142,7 +142,7 @@ define i32 @n4_extrause(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64
 ; CHECK-NEXT:    [[T1:%.*]] = shl i64 [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -32
-; CHECK-NEXT:    [[T3:%.*]] = lshr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = lshr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
diff --git a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-f.ll b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-f.ll
index 6163aa8c7ac0c..3839d1fabbf31 100644
--- a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-f.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-after-truncation-variant-f.ll
@@ -19,7 +19,7 @@ define i32 @t0_basic(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64
 ; CHECK-NEXT:    [[T1:%.*]] = shl i64 [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -32
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
@@ -53,7 +53,7 @@ define <8 x i32> @t1_vec_splat(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], splat (i32 -32)
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -82,7 +82,7 @@ define <8 x i32> @t2_vec_splat_undef(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -32, i32 -32, i32 -32, i32 -32, i32 -32, i32 undef, i32 -32>
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -111,7 +111,7 @@ define <8 x i32> @t3_vec_nonsplat(<8 x i64> %x, <8 x i32> %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>
 ; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i64> [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 undef, i32 64>
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact <8 x i64> [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr <8 x i64> [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])
 ; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])
 ; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
@@ -142,7 +142,7 @@ define i32 @n4_extrause(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64
 ; CHECK-NEXT:    [[T1:%.*]] = shl i64 [[X:%.*]], [[T0]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], -32
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
@@ -178,7 +178,7 @@ define i32 @n5_mask(i64 %x, i32 %nbits) {
 ; CHECK-NEXT:    call void @use64(i64 [[T0]])
 ; CHECK-NEXT:    call void @use64(i64 [[T1]])
 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
-; CHECK-NEXT:    [[T3:%.*]] = ashr exact i64 [[T1]], [[T0]]
+; CHECK-NEXT:    [[T3:%.*]] = ashr i64 [[T1]], [[T0]]
 ; CHECK-NEXT:    [[T4:%.*]] = trunc i64 [[T3]] to i32
 ; CHECK-NEXT:    [[T5:%.*]] = shl i32 [[T4]], [[T2]]
 ; CHECK-NEXT:    ret i32 [[T5]]
diff --git a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-e.ll b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-e.ll
index 1022a15fa04f5..2cfbb9d2ad3e3 100644
--- a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-e.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-e.ll
@@ -18,10 +18,11 @@ declare void @use32(i32)
 define i32 @t0_basic(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @t0_basic(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
-; CHECK-NEXT:    ret i32 [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[X]], [[NBITS]]
+; CHECK-NEXT:    ret i32 [[T2]]
 ;
   %t0 = shl i32 %x, %nbits
   %t1 = lshr i32 %t0, %nbits
@@ -34,7 +35,7 @@ define i32 @t0_basic(i32 %x, i32 %nbits) {
 define i32 @t1_bigger_shift(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @t1_bigger_shift(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[NBITS]], 1
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
@@ -59,7 +60,7 @@ declare void @use3xi32(<3 x i32>)
 define <3 x i32> @t2_vec_splat(<3 x i32> %x, <3 x i32> %nbits) {
 ; CHECK-LABEL: @t2_vec_splat(
 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i32> [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr <3 x i32> [[T0]], [[NBITS]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[NBITS]], splat (i32 1)
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T0]])
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T1]])
@@ -80,7 +81,7 @@ define <3 x i32> @t2_vec_splat(<3 x i32> %x, <3 x i32> %nbits) {
 define <3 x i32> @t3_vec_nonsplat(<3 x i32> %x, <3 x i32> %nbits) {
 ; CHECK-LABEL: @t3_vec_nonsplat(
 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i32> [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr <3 x i32> [[T0]], [[NBITS]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[NBITS]], <i32 1, i32 0, i32 2>
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T0]])
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T1]])
@@ -101,7 +102,7 @@ define <3 x i32> @t3_vec_nonsplat(<3 x i32> %x, <3 x i32> %nbits) {
 define <3 x i32> @t4_vec_undef(<3 x i32> %x, <3 x i32> %nbits) {
 ; CHECK-LABEL: @t4_vec_undef(
 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i32> [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr <3 x i32> [[T0]], [[NBITS]]
 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[NBITS]], <i32 1, i32 undef, i32 1>
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T0]])
 ; CHECK-NEXT:    call void @use3xi32(<3 x i32> [[T1]])
@@ -124,10 +125,11 @@ define <3 x i32> @t4_vec_undef(<3 x i32> %x, <3 x i32> %nbits) {
 define i32 @t5_nuw(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @t5_nuw(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
-; CHECK-NEXT:    ret i32 [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[X]], [[NBITS]]
+; CHECK-NEXT:    ret i32 [[T2]]
 ;
   %t0 = shl i32 %x, %nbits
   %t1 = lshr i32 %t0, %nbits
@@ -140,10 +142,11 @@ define i32 @t5_nuw(i32 %x, i32 %nbits) {
 define i32 @t6_nsw(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @t6_nsw(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
-; CHECK-NEXT:    ret i32 [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[X]], [[NBITS]]
+; CHECK-NEXT:    ret i32 [[T2]]
 ;
   %t0 = shl i32 %x, %nbits
   %t1 = lshr i32 %t0, %nbits
@@ -156,10 +159,11 @@ define i32 @t6_nsw(i32 %x, i32 %nbits) {
 define i32 @t7_nuw_nsw(i32 %x, i32 %nbits) {
 ; CHECK-LABEL: @t7_nuw_nsw(
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
-; CHECK-NEXT:    ret i32 [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[X]], [[NBITS]]
+; CHECK-NEXT:    ret i32 [[T2]]
 ;
   %t0 = shl i32 %x, %nbits
   %t1 = lshr i32 %t0, %nbits
@@ -179,7 +183,7 @@ define i32 @t8_assume_uge(i32 %x, i32 %masknbits, i32 %shiftnbits) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[SHIFTNBITS:%.*]], [[MASKNBITS:%.*]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
 ; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[MASKNBITS]]
-; CHECK-NEXT:    [[T1:%.*]] = lshr exact i32 [[T0]], [[MASKNBITS]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[T0]], [[MASKNBITS]]
 ; CHECK-NEXT:    call void @use32(i32 [[T0]])
 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
 ; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[T1]], [[SHIFTNBITS]]
diff --git a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-f.ll b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-f.ll
index f0a5f0ee3be61..f541f8c6b5a80 100644
--- a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-f.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-f.ll
@@ -18,10 +18,11 @@ declare void @use32(i32)
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/218861


More information about the llvm-commits mailing list