[llvm] a0c8017 - [InstCombine] do not add "nuw" to 1<<X if the "1" has undefined elements
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 26 10:37:15 PST 2022
Author: Sanjay Patel
Date: 2022-12-26T13:16:03-05:00
New Revision: a0c8017286de0cc34db41bfe7ab3176ca4f8ae64
URL: https://github.com/llvm/llvm-project/commit/a0c8017286de0cc34db41bfe7ab3176ca4f8ae64
DIFF: https://github.com/llvm/llvm-project/commit/a0c8017286de0cc34db41bfe7ab3176ca4f8ae64.diff
LOG: [InstCombine] do not add "nuw" to 1<<X if the "1" has undefined elements
This was noted as a potential miscompile in the post-commit feedback
for the patch that added this fold:
d4493dd1ed58ac3f1eab0
Added:
Modified:
llvm/include/llvm/IR/Constant.h
llvm/lib/IR/Constants.cpp
llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
llvm/test/Transforms/InstCombine/icmp-uge-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-eq-of-lshr-val-by-bits-and-0.ll
llvm/test/Transforms/InstCombine/icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 09fb2c98bff4b..778764062227c 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -111,6 +111,10 @@ class Constant : public User {
/// elements.
bool containsPoisonElement() const;
+ /// Return true if this is a vector constant that includes any strictly undef
+ /// (not poison) elements.
+ bool containsUndefElement() const;
+
/// Return true if this is a fixed width vector constant that includes
/// any constant expressions.
bool containsConstantExpression() const;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 9c8e2995b995b..a6c4c8b4c2186 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -337,6 +337,12 @@ bool Constant::containsPoisonElement() const {
this, [&](const auto *C) { return isa<PoisonValue>(C); });
}
+bool Constant::containsUndefElement() const {
+ return containsUndefinedElement(this, [&](const auto *C) {
+ return isa<UndefValue>(C) && !isa<PoisonValue>(C);
+ });
+}
+
bool Constant::containsConstantExpression() const {
if (auto *VTy = dyn_cast<FixedVectorType>(getType())) {
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index d4a6e9dcd62a3..1fce5179af6a7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1065,9 +1065,11 @@ Instruction *InstCombinerImpl::visitShl(BinaryOperator &I) {
return BinaryOperator::CreateLShr(
ConstantInt::get(Ty, APInt::getSignMask(BitWidth)), X);
- // The only way to shift out the 1 is with an over-shift, and that would
- // be poison either way.
- if (!I.hasNoUnsignedWrap()) {
+ // 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;
}
diff --git a/llvm/test/Transforms/InstCombine/icmp-uge-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-eq-of-lshr-val-by-bits-and-0.ll b/llvm/test/Transforms/InstCombine/icmp-uge-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-eq-of-lshr-val-by-bits-and-0.ll
index 2426d8cfb4d9b..b33ba41dcf31d 100644
--- a/llvm/test/Transforms/InstCombine/icmp-uge-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-eq-of-lshr-val-by-bits-and-0.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-uge-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-eq-of-lshr-val-by-bits-and-0.ll
@@ -54,7 +54,7 @@ define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef0(
-; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
diff --git a/llvm/test/Transforms/InstCombine/icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll b/llvm/test/Transforms/InstCombine/icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
index bcfc898a0c249..1c46e77486d89 100644
--- a/llvm/test/Transforms/InstCombine/icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-ult-of-add-of-shl-one-by-bits-to-allones-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
@@ -54,7 +54,7 @@ define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef0(
-; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
+; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
More information about the llvm-commits
mailing list