Skip to content

Commit 6f60a33

Browse files
committed
[InstCombine] Make (X|C1)^C2 -> X^(C1^C2) iff X&~C1 == 0 work for splat vectors
This also corrects the description to match what was actually implemented. The old comment said X^(C1|C2), but it implemented X^((C1|C2)&~(C1&C2)). I believe ((C1|C2)&~(C1&C2)) is equivalent to (C1^C2). Differential Revision: https://reviews.llvm.org/D36505 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310658 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 86c4bd6 commit 6f60a33

File tree

3 files changed

+38
-33
lines changed

3 files changed

+38
-33
lines changed

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,53 +2365,48 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
23652365
{
23662366
const APInt *RHSC;
23672367
if (match(Op1, m_APInt(RHSC))) {
2368-
Value *V;
2368+
Value *X;
23692369
const APInt *C;
2370-
if (match(Op0, m_Sub(m_APInt(C), m_Value(V)))) {
2370+
if (match(Op0, m_Sub(m_APInt(C), m_Value(X)))) {
23712371
// ~(c-X) == X-c-1 == X+(-c-1)
23722372
if (RHSC->isAllOnesValue()) {
23732373
Constant *NewC = ConstantInt::get(I.getType(), -(*C) - 1);
2374-
return BinaryOperator::CreateAdd(V, NewC);
2374+
return BinaryOperator::CreateAdd(X, NewC);
23752375
}
23762376
if (RHSC->isSignMask()) {
23772377
// (C - X) ^ signmask -> (C + signmask - X)
23782378
Constant *NewC = ConstantInt::get(I.getType(), *C + *RHSC);
2379-
return BinaryOperator::CreateSub(NewC, V);
2379+
return BinaryOperator::CreateSub(NewC, X);
23802380
}
2381-
} else if (match(Op0, m_Add(m_Value(V), m_APInt(C)))) {
2381+
} else if (match(Op0, m_Add(m_Value(X), m_APInt(C)))) {
23822382
// ~(X-c) --> (-c-1)-X
23832383
if (RHSC->isAllOnesValue()) {
23842384
Constant *NewC = ConstantInt::get(I.getType(), -(*C) - 1);
2385-
return BinaryOperator::CreateSub(NewC, V);
2385+
return BinaryOperator::CreateSub(NewC, X);
23862386
}
23872387
if (RHSC->isSignMask()) {
23882388
// (X + C) ^ signmask -> (X + C + signmask)
23892389
Constant *NewC = ConstantInt::get(I.getType(), *C + *RHSC);
2390-
return BinaryOperator::CreateAdd(V, NewC);
2390+
return BinaryOperator::CreateAdd(X, NewC);
23912391
}
23922392
}
2393+
2394+
// (X|C1)^C2 -> X^(C1^C2) iff X&~C1 == 0
2395+
if (match(Op0, m_Or(m_Value(X), m_APInt(C))) &&
2396+
MaskedValueIsZero(X, *C, 0, &I)) {
2397+
Constant *NewC = ConstantInt::get(I.getType(), *C ^ *RHSC);
2398+
Worklist.Add(cast<Instruction>(Op0));
2399+
I.setOperand(0, X);
2400+
I.setOperand(1, NewC);
2401+
return &I;
2402+
}
23932403
}
23942404
}
23952405

23962406
if (ConstantInt *RHSC = dyn_cast<ConstantInt>(Op1)) {
23972407
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
23982408
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
2399-
if (Op0I->getOpcode() == Instruction::Or) {
2400-
// (X|C1)^C2 -> X^(C1|C2) iff X&~C1 == 0
2401-
if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getValue(),
2402-
0, &I)) {
2403-
Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHSC);
2404-
// Anything in both C1 and C2 is known to be zero, remove it from
2405-
// NewRHS.
2406-
Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHSC);
2407-
NewRHS = ConstantExpr::getAnd(NewRHS,
2408-
ConstantExpr::getNot(CommonBits));
2409-
Worklist.Add(Op0I);
2410-
I.setOperand(0, Op0I->getOperand(0));
2411-
I.setOperand(1, NewRHS);
2412-
return &I;
2413-
}
2414-
} else if (Op0I->getOpcode() == Instruction::LShr) {
2409+
if (Op0I->getOpcode() == Instruction::LShr) {
24152410
// ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3)
24162411
// E1 = "X ^ C1"
24172412
BinaryOperator *E1;

test/Transforms/InstCombine/or.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,19 @@ define i16 @test23(i16 %A) {
143143
ret i16 %D
144144
}
145145

146+
define <2 x i16> @test23vec(<2 x i16> %A) {
147+
; CHECK-LABEL: @test23vec(
148+
; CHECK-NEXT: [[B:%.*]] = lshr <2 x i16> [[A:%.*]], <i16 1, i16 1>
149+
; CHECK-NEXT: [[D:%.*]] = xor <2 x i16> [[B]], <i16 -24575, i16 -24575>
150+
; CHECK-NEXT: ret <2 x i16> [[D]]
151+
;
152+
%B = lshr <2 x i16> %A, <i16 1, i16 1>
153+
;; fold or into xor
154+
%C = or <2 x i16> %B, <i16 -32768, i16 -32768>
155+
%D = xor <2 x i16> %C, <i16 8193, i16 8193>
156+
ret <2 x i16> %D
157+
}
158+
146159
; PR1738
147160
define i1 @test24(double %X, double %Y) {
148161
; CHECK-LABEL: @test24(

test/Transforms/InstCombine/select-with-bitwise-ops.ll

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,8 @@ define <2 x i32> @test65vec(<2 x i64> %x) {
273273
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 3, i64 3>
274274
; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
275275
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], <i32 2, i32 2>
276-
; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], <i32 40, i32 40>
277-
; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], <i32 2, i32 2>
278-
; CHECK-NEXT: ret <2 x i32> [[TMP5]]
276+
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], <i32 42, i32 42>
277+
; CHECK-NEXT: ret <2 x i32> [[TMP4]]
279278
;
280279
%1 = and <2 x i64> %x, <i64 16, i64 16>
281280
%2 = icmp ne <2 x i64> %1, zeroinitializer
@@ -302,9 +301,8 @@ define <2 x i32> @test66vec(<2 x i64> %x) {
302301
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 31, i64 31>
303302
; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
304303
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], <i32 2, i32 2>
305-
; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], <i32 40, i32 40>
306-
; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], <i32 2, i32 2>
307-
; CHECK-NEXT: ret <2 x i32> [[TMP5]]
304+
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], <i32 42, i32 42>
305+
; CHECK-NEXT: ret <2 x i32> [[TMP4]]
308306
;
309307
%1 = and <2 x i64> %x, <i64 4294967296, i64 4294967296>
310308
%2 = icmp ne <2 x i64> %1, zeroinitializer
@@ -344,10 +342,9 @@ define <2 x i32> @test67vec(<2 x i16> %x) {
344342
; CHECK-LABEL: @test67vec(
345343
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i16> [[X:%.*]], <i16 1, i16 1>
346344
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i16> [[TMP1]], <i16 2, i16 2>
347-
; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i16> [[TMP2]], <i16 40, i16 40>
348-
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i16> [[TMP3]], <i16 2, i16 2>
349-
; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i16> [[TMP4]] to <2 x i32>
350-
; CHECK-NEXT: ret <2 x i32> [[TMP5]]
345+
; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i16> [[TMP2]], <i16 42, i16 42>
346+
; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i16> [[TMP3]] to <2 x i32>
347+
; CHECK-NEXT: ret <2 x i32> [[TMP4]]
351348
;
352349
%1 = and <2 x i16> %x, <i16 4, i16 4>
353350
%2 = icmp ne <2 x i16> %1, zeroinitializer

0 commit comments

Comments
 (0)