Skip to content

Commit a8e39c2

Browse files
committed
Propagate NSW in ~((-X) | Y) --> (X - 1) & (~Y)
https://alive2.llvm.org/ce/z/qojyPF If -X is nsw, then X - 1 must be too. This is because -X can only be nsw if X is any number that is not INT_MIN. And if X is not INT_MIN, then X - 1 must be nsw.
1 parent 641ae74 commit a8e39c2

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4750,8 +4750,22 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {
47504750
BinaryOperator *NotVal;
47514751
if (match(NotOp, m_BinOp(NotVal))) {
47524752
// ~((-X) | Y) --> (X - 1) & (~Y)
4753+
if (match(NotVal,
4754+
m_OneUse(m_c_Or(m_OneUse(m_NSWNeg(m_Value(X))), m_Value(Y))))) {
4755+
// If -X is nsw, then X - 1 must be too.
4756+
// This is because -X can only be nsw if X is any number that is not
4757+
// INT_MIN. And if X is not INT_MIN, then X - 1 must be nsw.
4758+
Value *DecX = Builder.CreateAdd(X, ConstantInt::getAllOnesValue(Ty), "",
4759+
/*HasNUW=*/false, /*HasNSW=*/true);
4760+
Value *NotY = Builder.CreateNot(Y);
4761+
return BinaryOperator::CreateAnd(DecX, NotY);
4762+
}
4763+
47534764
if (match(NotVal,
47544765
m_OneUse(m_c_Or(m_OneUse(m_Neg(m_Value(X))), m_Value(Y))))) {
4766+
// If -X is nsw, then X - 1 must be too.
4767+
// This is because -X can only be nsw if X is any number that is not
4768+
// INT_MIN. And if X is not INT_MIN, then X - 1 must be nsw.
47554769
Value *DecX = Builder.CreateAdd(X, ConstantInt::getAllOnesValue(Ty));
47564770
Value *NotY = Builder.CreateNot(Y);
47574771
return BinaryOperator::CreateAnd(DecX, NotY);

llvm/test/Transforms/InstCombine/not.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ define <3 x i5> @not_or_neg_commute_vec(<3 x i5> %x, <3 x i5> %p) {
438438

439439
define i8 @not_or_neg_nsw(i8 %x, i8 %y) {
440440
; CHECK-LABEL: @not_or_neg_nsw(
441-
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
441+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[Y:%.*]], -1
442442
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X:%.*]], -1
443443
; CHECK-NEXT: [[NOT:%.*]] = and i8 [[TMP1]], [[TMP2]]
444444
; CHECK-NEXT: ret i8 [[NOT]]
@@ -452,7 +452,7 @@ define i8 @not_or_neg_nsw(i8 %x, i8 %y) {
452452
define <3 x i5> @not_or_neg_commute_vec_nsw(<3 x i5> %x, <3 x i5> %p) {
453453
; CHECK-LABEL: @not_or_neg_commute_vec_nsw(
454454
; CHECK-NEXT: [[Y:%.*]] = mul <3 x i5> [[P:%.*]], <i5 1, i5 2, i5 3>
455-
; CHECK-NEXT: [[TMP1:%.*]] = add <3 x i5> [[X:%.*]], splat (i5 -1)
455+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw <3 x i5> [[X:%.*]], splat (i5 -1)
456456
; CHECK-NEXT: [[TMP2:%.*]] = xor <3 x i5> [[Y]], splat (i5 -1)
457457
; CHECK-NEXT: [[NOT:%.*]] = and <3 x i5> [[TMP1]], [[TMP2]]
458458
; CHECK-NEXT: ret <3 x i5> [[NOT]]

0 commit comments

Comments
 (0)