[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:20 PDT 2026
https://github.com/Chennesxu created https://github.com/llvm/llvm-project/pull/218861
`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
>From ad5bd384e2688e5935ce8dd1a83a6af14940873f Mon Sep 17 00:00:00 2001
From: Chennes <xuchen359 at gmail.com>
Date: Sun, 23 Aug 2026 09:33:29 +0800
Subject: [PATCH 1/2] [InstCombine] Add tests for exact inference on shifts
with a shared operand
Both `shr (shl X, Y), Y` and `shr X, cttz(X)` infer 'exact' from repeated
uses of the same SSA value, which does not hold when that value may be
undef.
---
.../InstCombine/cttz-shift-exact.ll | 40 +++++++++++++
.../Transforms/InstCombine/shift-flags.ll | 56 +++++++++++++++++++
2 files changed, 96 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll b/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
index ee2f7757e4266..3f9fa8414320c 100644
--- a/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
+++ b/llvm/test/Transforms/InstCombine/cttz-shift-exact.ll
@@ -39,3 +39,43 @@ 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
+}
+
+; FIXME: 'exact' is invalid because %x may be undef.
+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 exact 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/shift-flags.ll b/llvm/test/Transforms/InstCombine/shift-flags.ll
index 08cf4821d85b4..3593d49d17fc8 100644
--- a/llvm/test/Transforms/InstCombine/shift-flags.ll
+++ b/llvm/test/Transforms/InstCombine/shift-flags.ll
@@ -117,3 +117,59 @@ define i8 @ashr_add_exact_fail(i8 %amt_in, i8 %cnt_in) {
%r = ashr i8 %amt, %cnt
ret i8 %r
}
+
+define i8 @ashr_shl_same_shamt_exact(i8 %x, i8 noundef %cnt) {
+; CHECK-LABEL: @ashr_shl_same_shamt_exact(
+; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[CNT:%.*]]
+; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[SHL]], [[CNT]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %shl = shl i8 %x, %cnt
+ %r = ashr i8 %shl, %cnt
+ ret i8 %r
+}
+
+define i8 @ashr_shl_same_shamt_exact_freeze(i8 %x, i8 %cnt_in) {
+; CHECK-LABEL: @ashr_shl_same_shamt_exact_freeze(
+; CHECK-NEXT: [[CNT:%.*]] = freeze i8 [[CNT_IN:%.*]]
+; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[CNT]]
+; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[SHL]], [[CNT]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %cnt = freeze i8 %cnt_in
+ %shl = shl i8 %x, %cnt
+ %r = ashr i8 %shl, %cnt
+ ret i8 %r
+}
+
+; FIXME: 'exact' is invalid because the shift amount may be undef.
+define i8 @ashr_shl_same_shamt_exact_fail(i8 %x, i8 %cnt_in) {
+; CHECK-LABEL: @ashr_shl_same_shamt_exact_fail(
+; CHECK-NEXT: [[CNT:%.*]] = and i8 [[CNT_IN:%.*]], 7
+; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[CNT]]
+; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[SHL]], [[CNT]]
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %cnt = and i8 %cnt_in, 7
+ %shl = shl i8 %x, %cnt
+ %r = ashr i8 %shl, %cnt
+ ret i8 %r
+}
+
+; FIXME: 'exact' is invalid because the shift amount may be undef.
+define i16 @ashr_shl_same_shamt_exact_fail_zext(i16 %x, i4 %n) {
+; CHECK-LABEL: @ashr_shl_same_shamt_exact_fail_zext(
+; CHECK-NEXT: [[HIGHBITS:%.*]] = lshr i16 [[X:%.*]], 1
+; CHECK-NEXT: [[SUB:%.*]] = sub i4 0, [[N:%.*]]
+; CHECK-NEXT: [[Z:%.*]] = zext i4 [[SUB]] to i16
+; CHECK-NEXT: [[SHL:%.*]] = shl i16 [[HIGHBITS]], [[Z]]
+; CHECK-NEXT: [[R:%.*]] = ashr exact i16 [[SHL]], [[Z]]
+; CHECK-NEXT: ret i16 [[R]]
+;
+ %highbits = lshr i16 %x, 1
+ %sub = sub i4 0, %n
+ %z = zext i4 %sub to i16
+ %shl = shl i16 %highbits, %z
+ %r = ashr i16 %shl, %z
+ ret i16 %r
+}
>From 81072176674d59a0dee7e886d535717195c00995 Mon Sep 17 00:00:00 2001
From: Chennes <xuchen359 at gmail.com>
Date: Sun, 23 Aug 2026 10:40:50 +0800
Subject: [PATCH 2/2] [InstCombine] Don't infer exact from an operand that may
be undef
setShiftFlags() infers 'exact' for `shr (shl X, Y), Y` and `shr X, cttz(X)`
from repeated uses of the same SSA value. That does not hold if the shared
value may be undef, because each use may observe a different value.
Fixes #217234.
---
.../InstCombine/InstCombineShifts.cpp | 7 ++--
.../canonicalize-shl-lshr-to-masking.ll | 2 +-
.../InstCombine/cttz-shift-exact.ll | 7 ++--
...nput-masking-after-truncation-variant-e.ll | 6 ++--
...dant-left-shift-input-masking-variant-e.ll | 2 +-
...nput-masking-after-truncation-variant-e.ll | 10 +++---
...nput-masking-after-truncation-variant-f.ll | 12 +++----
...dant-left-shift-input-masking-variant-e.ll | 30 +++++++++--------
...dant-left-shift-input-masking-variant-f.ll | 32 +++++++++++--------
.../redundant-right-shift-input-masking.ll | 8 ++---
llvm/test/Transforms/InstCombine/select.ll | 2 +-
llvm/test/Transforms/InstCombine/sext.ll | 2 +-
.../InstCombine/shift-by-signext.ll | 4 +--
.../Transforms/InstCombine/shift-flags.ll | 6 ++--
...signext-of-variable-high-bit-extraction.ll | 12 +++----
.../PhaseOrdering/two-shifts-by-sext.ll | 8 ++---
16 files changed, 79 insertions(+), 71 deletions(-)
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 3f9fa8414320c..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)
@@ -65,13 +65,12 @@ define i32 @test_cttz_ashr_freeze(i32 %x_in) {
ret i32 %sh
}
-; FIXME: 'exact' is invalid because %x may be undef.
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 exact i32 [[X]], [[CTTZ]]
+; CHECK-NEXT: [[SH:%.*]] = lshr i32 [[X]], [[CTTZ]]
; CHECK-NEXT: ret i32 [[SH]]
;
%x = or i32 %y, 4
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)
define i32 @t0_basic(i32 %x, i32 %nbits) {
; CHECK-LABEL: @t0_basic(
; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr 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 = ashr 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:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr 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:%.*]] = ashr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr <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:%.*]] = ashr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr <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:%.*]] = ashr exact <3 x i32> [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr <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:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr 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 = ashr 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:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr 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 = ashr 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:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr 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 = ashr 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:%.*]] = ashr exact i32 [[T0]], [[MASKNBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[T0]], [[MASKNBITS]]
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: call void @use32(i32 [[T1]])
; CHECK-NEXT: [[T2:%.*]] = shl i32 [[T1]], [[SHIFTNBITS]]
@@ -234,7 +238,7 @@ define i32 @n10_different_shamts1(i32 %x, i32 %nbits0, i32 %nbits1) {
define i32 @n11_shamt_is_smaller(i32 %x, i32 %nbits) {
; CHECK-LABEL: @n11_shamt_is_smaller(
; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[NBITS:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = ashr exact i32 [[T0]], [[NBITS]]
+; CHECK-NEXT: [[T1:%.*]] = ashr i32 [[T0]], [[NBITS]]
; CHECK-NEXT: [[T2:%.*]] = add i32 [[NBITS]], -1
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: call void @use32(i32 [[T2]])
diff --git a/llvm/test/Transforms/InstCombine/redundant-right-shift-input-masking.ll b/llvm/test/Transforms/InstCombine/redundant-right-shift-input-masking.ll
index ca65e07e2d853..657356a213a72 100644
--- a/llvm/test/Transforms/InstCombine/redundant-right-shift-input-masking.ll
+++ b/llvm/test/Transforms/InstCombine/redundant-right-shift-input-masking.ll
@@ -122,7 +122,7 @@ define i32 @t7_noncanonical_lshr_lshr_extrauses(i32 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[T1]])
-; CHECK-NEXT: [[T2:%.*]] = lshr exact i32 [[T1]], [[NBITS]]
+; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]]
; CHECK-NEXT: ret i32 [[T2]]
;
%t0 = lshr i32 %data, %nbits
@@ -139,7 +139,7 @@ define i32 @t8_noncanonical_lshr_ashr_extrauses(i32 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[T1]])
-; CHECK-NEXT: [[T2:%.*]] = ashr exact i32 [[T1]], [[NBITS]]
+; CHECK-NEXT: [[T2:%.*]] = ashr i32 [[T1]], [[NBITS]]
; CHECK-NEXT: ret i32 [[T2]]
;
%t0 = lshr i32 %data, %nbits
@@ -156,7 +156,7 @@ define i32 @t9_noncanonical_ashr_lshr_extrauses(i32 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[T1]])
-; CHECK-NEXT: [[T2:%.*]] = lshr exact i32 [[T1]], [[NBITS]]
+; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]]
; CHECK-NEXT: ret i32 [[T2]]
;
%t0 = ashr i32 %data, %nbits
@@ -173,7 +173,7 @@ define i32 @t10_noncanonical_ashr_ashr_extrauses(i32 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[T1]])
-; CHECK-NEXT: [[T2:%.*]] = ashr exact i32 [[T1]], [[NBITS]]
+; CHECK-NEXT: [[T2:%.*]] = ashr i32 [[T1]], [[NBITS]]
; CHECK-NEXT: ret i32 [[T2]]
;
%t0 = ashr i32 %data, %nbits
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index a1e84fad9a827..2cb7a906b4e65 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -2911,7 +2911,7 @@ define i32 @pr47322_more_poisonous_replacement(i32 %arg) {
; CHECK-SAME: i32 [[ARG:%.*]]) {
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG]], 0
; CHECK-NEXT: [[TRAILING:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
-; CHECK-NEXT: [[SHIFTED:%.*]] = lshr exact i32 [[ARG]], [[TRAILING]]
+; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i32 [[ARG]], [[TRAILING]]
; CHECK-NEXT: [[R1_SROA_0_1:%.*]] = select i1 [[CMP]], i32 0, i32 [[SHIFTED]]
; CHECK-NEXT: ret i32 [[R1_SROA_0_1]]
;
diff --git a/llvm/test/Transforms/InstCombine/sext.ll b/llvm/test/Transforms/InstCombine/sext.ll
index c72614d526036..e5fbc80a8c09b 100644
--- a/llvm/test/Transforms/InstCombine/sext.ll
+++ b/llvm/test/Transforms/InstCombine/sext.ll
@@ -182,7 +182,7 @@ define <2 x i32> @test10_vec_poison0(<2 x i32> %i) {
define <2 x i32> @test10_vec_poison1(<2 x i32> %i) {
; CHECK-LABEL: @test10_vec_poison1(
; CHECK-NEXT: [[D1:%.*]] = shl <2 x i32> [[I:%.*]], <i32 30, i32 undef>
-; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i32> [[D1]], <i32 30, i32 undef>
+; CHECK-NEXT: [[D:%.*]] = ashr <2 x i32> [[D1]], <i32 30, i32 undef>
; CHECK-NEXT: ret <2 x i32> [[D]]
;
%A = trunc <2 x i32> %i to <2 x i8>
diff --git a/llvm/test/Transforms/InstCombine/shift-by-signext.ll b/llvm/test/Transforms/InstCombine/shift-by-signext.ll
index f57d7f605c563..7fe4364cc0801 100644
--- a/llvm/test/Transforms/InstCombine/shift-by-signext.ll
+++ b/llvm/test/Transforms/InstCombine/shift-by-signext.ll
@@ -75,7 +75,7 @@ define i32 @t6_twoshifts(i32 %x, i8 %shamt) {
; CHECK: end:
; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32
; CHECK-NEXT: [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]
-; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[N0]], [[SHAMT_WIDE]]
+; CHECK-NEXT: [[R:%.*]] = ashr i32 [[N0]], [[SHAMT_WIDE]]
; CHECK-NEXT: ret i32 [[R]]
;
bb:
@@ -157,7 +157,7 @@ define i32 @n12_twoshifts_and_extrause(i32 %x, i8 %shamt) {
; CHECK: end:
; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32
; CHECK-NEXT: [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]
-; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[N0]], [[SHAMT_WIDE]]
+; CHECK-NEXT: [[R:%.*]] = ashr i32 [[N0]], [[SHAMT_WIDE]]
; CHECK-NEXT: call void @use32(i32 [[SHAMT_WIDE]])
; CHECK-NEXT: ret i32 [[R]]
;
diff --git a/llvm/test/Transforms/InstCombine/shift-flags.ll b/llvm/test/Transforms/InstCombine/shift-flags.ll
index 3593d49d17fc8..c29277b0586a5 100644
--- a/llvm/test/Transforms/InstCombine/shift-flags.ll
+++ b/llvm/test/Transforms/InstCombine/shift-flags.ll
@@ -142,12 +142,11 @@ define i8 @ashr_shl_same_shamt_exact_freeze(i8 %x, i8 %cnt_in) {
ret i8 %r
}
-; FIXME: 'exact' is invalid because the shift amount may be undef.
define i8 @ashr_shl_same_shamt_exact_fail(i8 %x, i8 %cnt_in) {
; CHECK-LABEL: @ashr_shl_same_shamt_exact_fail(
; CHECK-NEXT: [[CNT:%.*]] = and i8 [[CNT_IN:%.*]], 7
; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], [[CNT]]
-; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[SHL]], [[CNT]]
+; CHECK-NEXT: [[R:%.*]] = ashr i8 [[SHL]], [[CNT]]
; CHECK-NEXT: ret i8 [[R]]
;
%cnt = and i8 %cnt_in, 7
@@ -156,14 +155,13 @@ define i8 @ashr_shl_same_shamt_exact_fail(i8 %x, i8 %cnt_in) {
ret i8 %r
}
-; FIXME: 'exact' is invalid because the shift amount may be undef.
define i16 @ashr_shl_same_shamt_exact_fail_zext(i16 %x, i4 %n) {
; CHECK-LABEL: @ashr_shl_same_shamt_exact_fail_zext(
; CHECK-NEXT: [[HIGHBITS:%.*]] = lshr i16 [[X:%.*]], 1
; CHECK-NEXT: [[SUB:%.*]] = sub i4 0, [[N:%.*]]
; CHECK-NEXT: [[Z:%.*]] = zext i4 [[SUB]] to i16
; CHECK-NEXT: [[SHL:%.*]] = shl i16 [[HIGHBITS]], [[Z]]
-; CHECK-NEXT: [[R:%.*]] = ashr exact i16 [[SHL]], [[Z]]
+; CHECK-NEXT: [[R:%.*]] = ashr i16 [[SHL]], [[Z]]
; CHECK-NEXT: ret i16 [[R]]
;
%highbits = lshr i16 %x, 1
diff --git a/llvm/test/Transforms/InstCombine/variable-signext-of-variable-high-bit-extraction.ll b/llvm/test/Transforms/InstCombine/variable-signext-of-variable-high-bit-extraction.ll
index 55bad9a57b863..33baac01a7a73 100644
--- a/llvm/test/Transforms/InstCombine/variable-signext-of-variable-high-bit-extraction.ll
+++ b/llvm/test/Transforms/InstCombine/variable-signext-of-variable-high-bit-extraction.ll
@@ -301,7 +301,7 @@ define i32 @n8_extrause_bad(i64 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: call void @use32(i32 [[SIGNBIT_POSITIONED]])
-; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%skip_high = sub i32 64, %nbits
@@ -334,7 +334,7 @@ define i32 @n9(i64 %data, i32 %nbits) {
; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
-; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%skip_high = sub i32 63, %nbits ; not 64
@@ -365,7 +365,7 @@ define i32 @n10(i64 %data, i32 %nbits) {
; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 31, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
-; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%skip_high = sub i32 64, %nbits
@@ -396,7 +396,7 @@ define i32 @n11(i64 %data, i32 %nbits1, i32 %nbits2) {
; CHECK-NEXT: [[NUM_HIGH_BITS_TO_SMEAR_NARROW:%.*]] = sub i32 32, [[NBITS2:%.*]]
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[SIGNBIT_POSITIONED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
-; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[SIGNBIT_POSITIONED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%skip_high = sub i32 64, %nbits1 ; not %nbits2
@@ -493,7 +493,7 @@ define i32 @n13_extrause(i64 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: call void @use32(i32 [[HIGHBITS_CLEANED]])
-; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[RES]]
;
%skip_high = sub i32 64, %nbits
@@ -555,7 +555,7 @@ define i32 @n14_extrause(i64 %data, i32 %nbits) {
; CHECK-NEXT: call void @use32(i32 [[NUM_HIGH_BITS_TO_SMEAR_NARROW]])
; CHECK-NEXT: [[HIGHBITS_CLEANED:%.*]] = shl i32 [[EXTRACTED_NARROW]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: call void @use32(i32 [[HIGHBITS_CLEANED]])
-; CHECK-NEXT: [[RES:%.*]] = lshr exact i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
+; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[HIGHBITS_CLEANED]], [[NUM_HIGH_BITS_TO_SMEAR_NARROW]]
; CHECK-NEXT: ret i32 [[RES]]
;
%skip_high = sub i32 64, %nbits
diff --git a/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll b/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll
index 9cc9dbd4c9718..f3c507f180f4e 100644
--- a/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll
+++ b/llvm/test/Transforms/PhaseOrdering/two-shifts-by-sext.ll
@@ -31,7 +31,7 @@ define i32 @two_shifts_by_sext(i32 %val, i8 signext %len) {
; CHECK-LABEL: @two_shifts_by_sext(
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], [[CONV]]
+; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
; CHECK-NEXT: ret i32 [[SHR]]
;
%val.addr = alloca i32, align 4
@@ -52,7 +52,7 @@ define i32 @two_shifts_by_same_sext(i32 %val, i8 signext %len) {
; CHECK-LABEL: @two_shifts_by_same_sext(
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], [[CONV]]
+; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
; CHECK-NEXT: ret i32 [[SHR]]
;
%val.addr = alloca i32, align 4
@@ -76,7 +76,7 @@ define i32 @two_shifts_by_sext_with_extra_use(i32 %val, i8 signext %len) {
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
; CHECK-NEXT: tail call void @use_int32(i32 [[CONV]])
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], [[CONV]]
+; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
; CHECK-NEXT: ret i32 [[SHR]]
;
%val.addr = alloca i32, align 4
@@ -103,7 +103,7 @@ define i32 @two_shifts_by_same_sext_with_extra_use(i32 %val, i8 signext %len) {
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[LEN:%.*]] to i32
; CHECK-NEXT: tail call void @use_int32(i32 [[CONV]])
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VAL:%.*]], [[CONV]]
-; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], [[CONV]]
+; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SHL]], [[CONV]]
; CHECK-NEXT: ret i32 [[SHR]]
;
%val.addr = alloca i32, align 4
More information about the llvm-commits
mailing list