Skip to content

Commit 49c0977

Browse files
committed
[InstCombine] Propagate nsw in (sub (and Op1, (neg X)), Op1) --> neg (and Op1, (add X, -1))
https://alive2.llvm.org/ce/z/xSs-jy
1 parent b9adc4a commit 49c0977

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,10 +2588,25 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
25882588
{
25892589
// (sub (and Op1, (neg X)), Op1) --> neg (and Op1, (add X, -1))
25902590
Value *X;
2591-
if (match(Op0, m_OneUse(m_c_And(m_Specific(Op1),
2592-
m_OneUse(m_Neg(m_Value(X))))))) {
2593-
return BinaryOperator::CreateNeg(Builder.CreateAnd(
2594-
Op1, Builder.CreateAdd(X, Constant::getAllOnesValue(I.getType()))));
2591+
BinaryOperator *NegInst;
2592+
if (match(Op0,
2593+
m_OneUse(m_c_And(m_Specific(Op1), m_OneUse(m_BinOp(NegInst))))) &&
2594+
match(NegInst, m_Neg(m_Value(X)))) {
2595+
2596+
// If neg X is nsw, then X - 1 must be too
2597+
bool AddHasNSW = NegInst->hasNoSignedWrap();
2598+
2599+
// If the original sub is nsw, then the final neg must be too
2600+
bool NegHasNSW = I.hasNoSignedWrap();
2601+
2602+
Value *Add =
2603+
Builder.CreateAdd(X, Constant::getAllOnesValue(I.getType()), "",
2604+
/*HasNUW=*/false, /*HasNSW=*/AddHasNSW);
2605+
Value *And = Builder.CreateAnd(Op1, Add);
2606+
2607+
// Use CreateNSWNeg or CreateNeg based on the flag
2608+
return NegHasNSW ? BinaryOperator::CreateNSWNeg(And)
2609+
: BinaryOperator::CreateNeg(And);
25952610
}
25962611
}
25972612

llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,45 @@ define i8 @t0(i8 %x, i8 %y) {
2525
ret i8 %negbias
2626
}
2727

28+
define i8 @t0_nsw(i8 %x, i8 %y) {
29+
; CHECK-LABEL: @t0_nsw(
30+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[Y:%.*]], -1
31+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
32+
; CHECK-NEXT: [[NEGBIAS:%.*]] = sub i8 0, [[TMP2]]
33+
; CHECK-NEXT: ret i8 [[NEGBIAS]]
34+
;
35+
%negy = sub nsw i8 0, %y
36+
%unbiasedx = and i8 %negy, %x
37+
%negbias = sub i8 %unbiasedx, %x
38+
ret i8 %negbias
39+
}
40+
41+
define i8 @t0_nsw_2(i8 %x, i8 %y) {
42+
; CHECK-LABEL: @t0_nsw_2(
43+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
44+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
45+
; CHECK-NEXT: [[NEGBIAS:%.*]] = sub nsw i8 0, [[TMP2]]
46+
; CHECK-NEXT: ret i8 [[NEGBIAS]]
47+
;
48+
%negy = sub i8 0, %y
49+
%unbiasedx = and i8 %negy, %x
50+
%negbias = sub nsw i8 %unbiasedx, %x
51+
ret i8 %negbias
52+
}
53+
54+
define i8 @t0_nsw_3(i8 %x, i8 %y) {
55+
; CHECK-LABEL: @t0_nsw_3(
56+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[Y:%.*]], -1
57+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
58+
; CHECK-NEXT: [[NEGBIAS:%.*]] = sub nsw i8 0, [[TMP2]]
59+
; CHECK-NEXT: ret i8 [[NEGBIAS]]
60+
;
61+
%negy = sub nsw i8 0, %y
62+
%unbiasedx = and i8 %negy, %x
63+
%negbias = sub nsw i8 %unbiasedx, %x
64+
ret i8 %negbias
65+
}
66+
2867
declare i8 @gen8()
2968

3069
define i8 @t1_commutative(i8 %y) {

0 commit comments

Comments
 (0)