-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[InstCombine] Infer shift flags with unknown shamt #72535
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Yingwei Zheng (dtcxzyw) ChangesThis patch improves the shift amount range calculation by taking account of Related patch: 2dd52b4 This missed optimization is discovered with the help of AliveToolkit/alive2#962. Patch is 107.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/72535.diff 38 Files Affected:
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 01eb8532d1f56d2..ba7bfcab03482f6 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -888,6 +888,11 @@ ConstantRange computeConstantRange(const Value *V, bool ForSigned,
const DominatorTree *DT = nullptr,
unsigned Depth = 0);
+/// Combine constant ranges from computeConstantRange() and computeKnownBits().
+ConstantRange
+computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
+ bool ForSigned, const SimplifyQuery &SQ);
+
/// Return true if this function can prove that the instruction I will
/// always transfer execution to one of its successors (including the next
/// instruction that follows within a basic block). E.g. this is not
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5f5d7e07cac1e46..b166806f0ec0e2a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6292,10 +6292,10 @@ static OverflowResult mapOverflowResult(ConstantRange::OverflowResult OR) {
}
/// Combine constant ranges from computeConstantRange() and computeKnownBits().
-static ConstantRange
-computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
- bool ForSigned,
- const SimplifyQuery &SQ) {
+ConstantRange
+llvm::computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
+ bool ForSigned,
+ const SimplifyQuery &SQ) {
ConstantRange CR1 =
ConstantRange::fromKnownBits(V.getKnownBits(SQ), ForSigned);
ConstantRange CR2 = computeConstantRange(V, ForSigned, SQ.IIQ.UseInstrInfo);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9d4a2cc08cca30c..cf87ae3ace5d1a2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -12,6 +12,7 @@
#include "InstCombineInternal.h"
#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"
@@ -962,16 +963,13 @@ static bool setShiftFlags(BinaryOperator &I, const SimplifyQuery &Q) {
}
// Compute what we know about shift count.
- KnownBits KnownCnt =
- computeKnownBits(I.getOperand(1), Q.DL, /*Depth*/ 0, Q.AC, Q.CxtI, Q.DT);
- // If we know nothing about shift count or its a poison shift, we won't be
- // able to prove anything so return before computing shift amount.
- if (KnownCnt.isUnknown())
- return false;
+ ConstantRange KnownCnt = computeConstantRangeIncludingKnownBits(
+ I.getOperand(1), /* ForSigned */ false, Q);
unsigned BitWidth = KnownCnt.getBitWidth();
- APInt MaxCnt = KnownCnt.getMaxValue();
- if (MaxCnt.uge(BitWidth))
- return false;
+ // Since shift produces a poison value if RHS is equal to or larger than the
+ // bit width, we can safely assume that RHS is less than the bit width.
+ APInt MaxCnt(BitWidth, BitWidth - 1);
+ MaxCnt = APIntOps::umin(MaxCnt, KnownCnt.getUnsignedMax());
KnownBits KnownAmt =
computeKnownBits(I.getOperand(0), Q.DL, /*Depth*/ 0, Q.AC, Q.CxtI, Q.DT);
diff --git a/llvm/test/Transforms/InstCombine/and-narrow.ll b/llvm/test/Transforms/InstCombine/and-narrow.ll
index c8c720f5fbc5534..0cc74008144b738 100644
--- a/llvm/test/Transforms/InstCombine/and-narrow.ll
+++ b/llvm/test/Transforms/InstCombine/and-narrow.ll
@@ -190,7 +190,7 @@ define <2 x i16> @zext_lshr_vec_undef(<2 x i8> %x) {
define <2 x i16> @zext_shl_vec_overshift(<2 x i8> %x) {
; CHECK-LABEL: @zext_shl_vec_overshift(
; CHECK-NEXT: [[Z:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i16>
-; CHECK-NEXT: [[B:%.*]] = shl <2 x i16> [[Z]], <i16 8, i16 2>
+; CHECK-NEXT: [[B:%.*]] = shl nuw <2 x i16> [[Z]], <i16 8, i16 2>
; CHECK-NEXT: [[R:%.*]] = and <2 x i16> [[B]], [[Z]]
; CHECK-NEXT: ret <2 x i16> [[R]]
;
diff --git a/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll b/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
index 8bfaa23c88bb4ea..78f4550464681e5 100644
--- a/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
+++ b/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
@@ -150,9 +150,9 @@ define i8 @lshr_add_fail(i8 %x) {
define i8 @ashr_add_fail(i8 %x) {
; CHECK-LABEL: define i8 @ashr_add_fail
; CHECK-SAME: (i8 [[X:%.*]]) {
-; CHECK-NEXT: [[SHIFT:%.*]] = ashr i8 -128, [[X]]
+; CHECK-NEXT: [[SHIFT:%.*]] = ashr exact i8 -128, [[X]]
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 1
-; CHECK-NEXT: [[SHIFT2:%.*]] = ashr i8 -128, [[ADD]]
+; CHECK-NEXT: [[SHIFT2:%.*]] = ashr exact i8 -128, [[ADD]]
; CHECK-NEXT: [[BINOP:%.*]] = add i8 [[SHIFT]], [[SHIFT2]]
; CHECK-NEXT: ret i8 [[BINOP]]
;
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll b/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
index 00e2bdf7b8ef83e..cde8efbafc5e5a8 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
@@ -15,7 +15,7 @@
define i8 @positive_samevar(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -62,7 +62,7 @@ define i8 @positive_biggershl(i8 %x) {
define i8 @positive_samevar_shlnuw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnuw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -109,7 +109,7 @@ define i8 @positive_biggershl_shlnuw(i8 %x) {
define i8 @positive_samevar_shlnsw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnsw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -156,7 +156,7 @@ define i8 @positive_biggershl_shlnsw(i8 %x) {
define i8 @positive_samevar_shlnuwnsw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnuwnsw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -371,7 +371,7 @@ define i8 @positive_biggershl_shlnuwnsw_ashrexact(i8 %x) {
define <2 x i8> @positive_samevar_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @positive_samevar_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i8> [[RET]]
;
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
index 624b9baa372810a..dfd67eae8aafd42 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
@@ -142,7 +142,7 @@ declare void @use8(i8)
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
@@ -158,7 +158,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
@@ -174,7 +174,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T2]])
@@ -191,7 +191,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse3(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -209,7 +209,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
define i1 @oneuse4(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse4(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -228,7 +228,7 @@ define i1 @oneuse4(i8 %x, i8 %y) {
define i1 @oneuse5(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse5(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -253,7 +253,7 @@ define i1 @oneuse5(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[NOTX:%.*]]
@@ -283,7 +283,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
index 4e1b90a476a2601..608e133ec7f73cd 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
@@ -142,7 +142,7 @@ declare void @use8(i8)
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
@@ -158,7 +158,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
@@ -174,7 +174,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T2]])
@@ -191,7 +191,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse3(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -209,7 +209,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
define i1 @oneuse4(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse4(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -228,7 +228,7 @@ define i1 @oneuse4(i8 %x, i8 %y) {
define i1 @oneuse5(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse5(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -253,7 +253,7 @@ define i1 @oneuse5(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[NOTX:%.*]]
@@ -283,7 +283,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
index 75de1dc6d07a222..a65be1e9ceeca3c 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
@@ -249,7 +249,7 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
index a92f4a9d9543112..f156d9bf007cbb0 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
@@ -249,7 +249,7 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
index 4ff27b787ed4e15..81f9fe4a3d181a2 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
@@ -20,7 +20,7 @@ declare void @use3i8(<3 x i8>)
define i1 @p0(i8 %x, i8 %y) {
; CHECK-LABEL: @p0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
@@ -40,7 +40,7 @@ define i1 @p0(i8 %x, i8 %y) {
define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @p1_vec(
-; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact <2 x i8> [[T0]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp uge <2 x i8> [[T1]], [[X:%.*]]
@@ -78,7 +78,7 @@ declare i8 @gen8()
define i1 @c0(i8 %y) {
; CHECK-LABEL: @c0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -96,7 +96,7 @@ define i1 @c0(i8 %y) {
define i1 @c1(i8 %y) {
; CHECK-LABEL: @c1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -114,7 +114,7 @@ define i1 @c1(i8 %y) {
define i1 @c2(i8 %y) {
; CHECK-LABEL: @c2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -136,7 +136,7 @@ define i1 @c2(i8 %y) {
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -154,7 +154,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -173,7 +173,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -198,7 +198,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -230,7 +230,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y1, i8 %y2) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y1:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y1:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr i8 [[T0]], [[Y2:%.*]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll
index 3c69d6b4c14a762..321a1159d0af7a8 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-...
[truncated]
|
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesThis patch improves the shift amount range calculation by taking account of Related patch: 2dd52b4 This missed optimization is discovered with the help of AliveToolkit/alive2#962. Patch is 107.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/72535.diff 38 Files Affected:
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 01eb8532d1f56d2..ba7bfcab03482f6 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -888,6 +888,11 @@ ConstantRange computeConstantRange(const Value *V, bool ForSigned,
const DominatorTree *DT = nullptr,
unsigned Depth = 0);
+/// Combine constant ranges from computeConstantRange() and computeKnownBits().
+ConstantRange
+computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
+ bool ForSigned, const SimplifyQuery &SQ);
+
/// Return true if this function can prove that the instruction I will
/// always transfer execution to one of its successors (including the next
/// instruction that follows within a basic block). E.g. this is not
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5f5d7e07cac1e46..b166806f0ec0e2a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6292,10 +6292,10 @@ static OverflowResult mapOverflowResult(ConstantRange::OverflowResult OR) {
}
/// Combine constant ranges from computeConstantRange() and computeKnownBits().
-static ConstantRange
-computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
- bool ForSigned,
- const SimplifyQuery &SQ) {
+ConstantRange
+llvm::computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
+ bool ForSigned,
+ const SimplifyQuery &SQ) {
ConstantRange CR1 =
ConstantRange::fromKnownBits(V.getKnownBits(SQ), ForSigned);
ConstantRange CR2 = computeConstantRange(V, ForSigned, SQ.IIQ.UseInstrInfo);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9d4a2cc08cca30c..cf87ae3ace5d1a2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -12,6 +12,7 @@
#include "InstCombineInternal.h"
#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"
@@ -962,16 +963,13 @@ static bool setShiftFlags(BinaryOperator &I, const SimplifyQuery &Q) {
}
// Compute what we know about shift count.
- KnownBits KnownCnt =
- computeKnownBits(I.getOperand(1), Q.DL, /*Depth*/ 0, Q.AC, Q.CxtI, Q.DT);
- // If we know nothing about shift count or its a poison shift, we won't be
- // able to prove anything so return before computing shift amount.
- if (KnownCnt.isUnknown())
- return false;
+ ConstantRange KnownCnt = computeConstantRangeIncludingKnownBits(
+ I.getOperand(1), /* ForSigned */ false, Q);
unsigned BitWidth = KnownCnt.getBitWidth();
- APInt MaxCnt = KnownCnt.getMaxValue();
- if (MaxCnt.uge(BitWidth))
- return false;
+ // Since shift produces a poison value if RHS is equal to or larger than the
+ // bit width, we can safely assume that RHS is less than the bit width.
+ APInt MaxCnt(BitWidth, BitWidth - 1);
+ MaxCnt = APIntOps::umin(MaxCnt, KnownCnt.getUnsignedMax());
KnownBits KnownAmt =
computeKnownBits(I.getOperand(0), Q.DL, /*Depth*/ 0, Q.AC, Q.CxtI, Q.DT);
diff --git a/llvm/test/Transforms/InstCombine/and-narrow.ll b/llvm/test/Transforms/InstCombine/and-narrow.ll
index c8c720f5fbc5534..0cc74008144b738 100644
--- a/llvm/test/Transforms/InstCombine/and-narrow.ll
+++ b/llvm/test/Transforms/InstCombine/and-narrow.ll
@@ -190,7 +190,7 @@ define <2 x i16> @zext_lshr_vec_undef(<2 x i8> %x) {
define <2 x i16> @zext_shl_vec_overshift(<2 x i8> %x) {
; CHECK-LABEL: @zext_shl_vec_overshift(
; CHECK-NEXT: [[Z:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i16>
-; CHECK-NEXT: [[B:%.*]] = shl <2 x i16> [[Z]], <i16 8, i16 2>
+; CHECK-NEXT: [[B:%.*]] = shl nuw <2 x i16> [[Z]], <i16 8, i16 2>
; CHECK-NEXT: [[R:%.*]] = and <2 x i16> [[B]], [[Z]]
; CHECK-NEXT: ret <2 x i16> [[R]]
;
diff --git a/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll b/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
index 8bfaa23c88bb4ea..78f4550464681e5 100644
--- a/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
+++ b/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll
@@ -150,9 +150,9 @@ define i8 @lshr_add_fail(i8 %x) {
define i8 @ashr_add_fail(i8 %x) {
; CHECK-LABEL: define i8 @ashr_add_fail
; CHECK-SAME: (i8 [[X:%.*]]) {
-; CHECK-NEXT: [[SHIFT:%.*]] = ashr i8 -128, [[X]]
+; CHECK-NEXT: [[SHIFT:%.*]] = ashr exact i8 -128, [[X]]
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 1
-; CHECK-NEXT: [[SHIFT2:%.*]] = ashr i8 -128, [[ADD]]
+; CHECK-NEXT: [[SHIFT2:%.*]] = ashr exact i8 -128, [[ADD]]
; CHECK-NEXT: [[BINOP:%.*]] = add i8 [[SHIFT]], [[SHIFT2]]
; CHECK-NEXT: ret i8 [[BINOP]]
;
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll b/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
index 00e2bdf7b8ef83e..cde8efbafc5e5a8 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-ashr-shl-to-masking.ll
@@ -15,7 +15,7 @@
define i8 @positive_samevar(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -62,7 +62,7 @@ define i8 @positive_biggershl(i8 %x) {
define i8 @positive_samevar_shlnuw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnuw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -109,7 +109,7 @@ define i8 @positive_biggershl_shlnuw(i8 %x) {
define i8 @positive_samevar_shlnsw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnsw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -156,7 +156,7 @@ define i8 @positive_biggershl_shlnsw(i8 %x) {
define i8 @positive_samevar_shlnuwnsw(i8 %x, i8 %y) {
; CHECK-LABEL: @positive_samevar_shlnuwnsw(
-; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret i8 [[RET]]
;
@@ -371,7 +371,7 @@ define i8 @positive_biggershl_shlnuwnsw_ashrexact(i8 %x) {
define <2 x i8> @positive_samevar_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @positive_samevar_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = shl nsw <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
; CHECK-NEXT: [[RET:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i8> [[RET]]
;
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
index 624b9baa372810a..dfd67eae8aafd42 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
@@ -142,7 +142,7 @@ declare void @use8(i8)
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
@@ -158,7 +158,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
@@ -174,7 +174,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T2]])
@@ -191,7 +191,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse3(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -209,7 +209,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
define i1 @oneuse4(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse4(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -228,7 +228,7 @@ define i1 @oneuse4(i8 %x, i8 %y) {
define i1 @oneuse5(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse5(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -253,7 +253,7 @@ define i1 @oneuse5(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[NOTX:%.*]]
@@ -283,7 +283,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
index 4e1b90a476a2601..608e133ec7f73cd 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
@@ -142,7 +142,7 @@ declare void @use8(i8)
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
@@ -158,7 +158,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
@@ -174,7 +174,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T2]])
@@ -191,7 +191,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse3(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -209,7 +209,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
define i1 @oneuse4(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse4(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -228,7 +228,7 @@ define i1 @oneuse4(i8 %x, i8 %y) {
define i1 @oneuse5(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse5(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -253,7 +253,7 @@ define i1 @oneuse5(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[NOTX:%.*]]
@@ -283,7 +283,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
index 75de1dc6d07a222..a65be1e9ceeca3c 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
@@ -249,7 +249,7 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
index a92f4a9d9543112..f156d9bf007cbb0 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
@@ -249,7 +249,7 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
index 4ff27b787ed4e15..81f9fe4a3d181a2 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-eq-to-icmp-ule.ll
@@ -20,7 +20,7 @@ declare void @use3i8(<3 x i8>)
define i1 @p0(i8 %x, i8 %y) {
; CHECK-LABEL: @p0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
@@ -40,7 +40,7 @@ define i1 @p0(i8 %x, i8 %y) {
define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @p1_vec(
-; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact <2 x i8> [[T0]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp uge <2 x i8> [[T1]], [[X:%.*]]
@@ -78,7 +78,7 @@ declare i8 @gen8()
define i1 @c0(i8 %y) {
; CHECK-LABEL: @c0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -96,7 +96,7 @@ define i1 @c0(i8 %y) {
define i1 @c1(i8 %y) {
; CHECK-LABEL: @c1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -114,7 +114,7 @@ define i1 @c1(i8 %y) {
define i1 @c2(i8 %y) {
; CHECK-LABEL: @c2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
@@ -136,7 +136,7 @@ define i1 @c2(i8 %y) {
define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -154,7 +154,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse1(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -173,7 +173,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
define i1 @oneuse2(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: call void @use8(i8 [[T1]])
@@ -198,7 +198,7 @@ define i1 @oneuse2(i8 %x, i8 %y) {
define i1 @n0(i8 %x, i8 %y, i8 %notx) {
; CHECK-LABEL: @n0(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr exact i8 [[T0]], [[Y]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
@@ -230,7 +230,7 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y1, i8 %y2) {
; CHECK-LABEL: @n2(
-; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[Y1:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y1:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = lshr i8 [[T0]], [[Y2:%.*]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll
index 3c69d6b4c14a762..321a1159d0af7a8 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v4-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have any compile-time impact?
Compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=59b2301508ecd97175f4093039bbf887f6d5b484&to=561a3c51afb2816ca1ab20fef16fafc69f590681&stat=instructions:u |
I think there are really two independent changes here: 1. Handle unknown shift amounts and 2. use constant range. The majority of the test changes is caused by 1. Can you please reduce this PR to just the unknown shift amount handling and separate ConstantRange into a separate one? |
0913fe1
to
53f4e32
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I believe you can also remove
llvm-project/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
Lines 1229 to 1236 in ec42d54
// The only way to shift out the 1 is with an over-shift, so that would | |
// be poison with or without "nuw". Undef is excluded because (undef << X) | |
// is not undef (it is zero). | |
Constant *ConstantOne = cast<Constant>(Op0); | |
if (!I.hasNoUnsignedWrap() && !ConstantOne->containsUndefElement()) { | |
I.setHasNoUnsignedWrap(); | |
return &I; | |
} |
This patch handles `poison` elements of non-splat vectors in `computeKnownBits`. It addresses test changes after I delete the duplicate logic in #72535. See also @nikic's comment: #72535 (review)
53f4e32
to
01ecea6
Compare
This patch handles `poison` elements of non-splat vectors in `computeKnownBits`. It addresses test changes after I delete the duplicate logic in llvm#72535. See also @nikic's comment: llvm#72535 (review)
This patch handles `poison` elements of non-splat vectors in `computeKnownBits`. It addresses test changes after I delete the duplicate logic in llvm#72535. See also @nikic's comment: llvm#72535 (review)
Alive2: https://alive2.llvm.org/ce/z/82Wr3q
Related patch: 2dd52b4
This missed optimization is discovered with the help of AliveToolkit/alive2#962.