Skip to content

Commit 4444a7e

Browse files
authored
[InstSimplify] Simplify the expression (a^c)&(a^~c) to zero and (a^c) | (a^~c) to minus one (#76637)
Changes the InstSimplify pass of the LLVM optimizer, such that the aforementioned expression is reduced to zero if c2==~c1. Alive2: https://alive2.llvm.org/ce/z/xkQiid Fixes #75692.
1 parent 771fd1a commit 4444a7e

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,13 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
22042204
match(Op1, m_c_Xor(m_Specific(Or), m_Specific(Y))))
22052205
return Constant::getNullValue(Op0->getType());
22062206

2207+
const APInt *C1;
2208+
Value *A;
2209+
// (A ^ C) & (A ^ ~C) -> 0
2210+
if (match(Op0, m_Xor(m_Value(A), m_APInt(C1))) &&
2211+
match(Op1, m_Xor(m_Specific(A), m_SpecificInt(~*C1))))
2212+
return Constant::getNullValue(Op0->getType());
2213+
22072214
if (Op0->getType()->isIntOrIntVectorTy(1)) {
22082215
if (std::optional<bool> Implied = isImpliedCondition(Op0, Op1, Q.DL)) {
22092216
// If Op0 is true implies Op1 is true, then Op0 is a subset of Op1.
@@ -2473,6 +2480,11 @@ static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
24732480
if (Value *V = threadBinOpOverPHI(Instruction::Or, Op0, Op1, Q, MaxRecurse))
24742481
return V;
24752482

2483+
// (A ^ C) | (A ^ ~C) -> -1, i.e. all bits set to one.
2484+
if (match(Op0, m_Xor(m_Value(A), m_APInt(C1))) &&
2485+
match(Op1, m_Xor(m_Specific(A), m_SpecificInt(~*C1))))
2486+
return Constant::getAllOnesValue(Op0->getType());
2487+
24762488
if (Op0->getType()->isIntOrIntVectorTy(1)) {
24772489
if (std::optional<bool> Implied =
24782490
isImpliedCondition(Op0, Op1, Q.DL, false)) {

llvm/test/Transforms/InstCombine/and-xor-merge.ll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,42 @@ define i32 @PR38781(i32 %a, i32 %b) {
4040
%and = and i32 %b.lobit.not, %a.lobit.not
4141
ret i32 %and
4242
}
43+
44+
; (a ^ 4) & (a ^ ~4) -> 0
45+
define i32 @PR75692_1(i32 %x) {
46+
; CHECK-LABEL: @PR75692_1
47+
; CHECK-NEXT: ret i32 0
48+
;
49+
%t2 = xor i32 %x, 4
50+
%t3 = xor i32 %x, -5
51+
%t4 = and i32 %t2, %t3
52+
ret i32 %t4
53+
}
54+
55+
; (a ^ 4) & (a ^ 3) is not zero
56+
define i32 @PR75692_2(i32 %x) {
57+
; CHECK-LABEL: @PR75692_2
58+
; CHECK-NEXT: %t2 = xor i32 %x, 4
59+
; CHECK-NEXT: %t3 = xor i32 %x, -4
60+
; CHECK-NEXT: %t4 = and i32 %t2, %t3
61+
; CHECK-NEXT: ret i32 %t4
62+
;
63+
%t2 = xor i32 %x, 4
64+
%t3 = xor i32 %x, -4
65+
%t4 = and i32 %t2, %t3
66+
ret i32 %t4
67+
}
68+
69+
; (a ^ 4) & (b ^ ~4) is not zero, since a != b is possible
70+
define i32 @PR75692_3(i32 %x, i32 %y) {
71+
; CHECK-LABEL: @PR75692_3
72+
; CHECK-NEXT: %t2 = xor i32 %x, 4
73+
; CHECK-NEXT: %t3 = xor i32 %y, -5
74+
; CHECK-NEXT: %t4 = and i32 %t2, %t3
75+
; CHECK-NEXT: ret i32 %t4
76+
;
77+
%t2 = xor i32 %x, 4
78+
%t3 = xor i32 %y, -5
79+
%t4 = and i32 %t2, %t3
80+
ret i32 %t4
81+
}

llvm/test/Transforms/InstCombine/or-xor.ll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,3 +1055,42 @@ define i8 @or_nand_xor_common_op_commute3_use3(i8 %x, i8 %y, i8 %z) {
10551055
%r = or i8 %xor, %nand
10561056
ret i8 %r
10571057
}
1058+
1059+
; (a ^ 4) & (a ^ ~4) -> -1
1060+
define i32 @PR75692_1(i32 %x) {
1061+
; CHECK-LABEL: @PR75692_1(
1062+
; CHECK-NEXT: ret i32 -1
1063+
;
1064+
%t2 = xor i32 %x, 4
1065+
%t3 = xor i32 %x, -5
1066+
%t4 = or i32 %t2, %t3
1067+
ret i32 %t4
1068+
}
1069+
1070+
; (a ^ 4) & (a ^ 3) is not -1
1071+
define i32 @PR75692_2(i32 %x) {
1072+
; CHECK-LABEL: @PR75692_2
1073+
; CHECK-NEXT: %t2 = xor i32 %x, 4
1074+
; CHECK-NEXT: %t3 = xor i32 %x, -4
1075+
; CHECK-NEXT: %t4 = or i32 %t2, %t3
1076+
; CHECK-NEXT: ret i32 %t4
1077+
;
1078+
%t2 = xor i32 %x, 4
1079+
%t3 = xor i32 %x, -4
1080+
%t4 = or i32 %t2, %t3
1081+
ret i32 %t4
1082+
}
1083+
1084+
; (a ^ 4) & (b ^ ~4) is not -1, since a != b is possible
1085+
define i32 @PR75692_3(i32 %x, i32 %y) {
1086+
; CHECK-LABEL: @PR75692_3
1087+
; CHECK-NEXT: %t2 = xor i32 %x, 4
1088+
; CHECK-NEXT: %t3 = xor i32 %y, -5
1089+
; CHECK-NEXT: %t4 = or i32 %t2, %t3
1090+
; CHECK-NEXT: ret i32 %t4
1091+
;
1092+
%t2 = xor i32 %x, 4
1093+
%t3 = xor i32 %y, -5
1094+
%t4 = or i32 %t2, %t3
1095+
ret i32 %t4
1096+
}

0 commit comments

Comments
 (0)