Skip to content

Commit 534701d

Browse files
committed
[InstCombine] Handle commuted variants in or of xor pattern
This pattern only handled commutation in the "or", while all involved operations are commutative. Make sure we handle all sixteen patterns.
1 parent 90ffaa6 commit 534701d

File tree

2 files changed

+22
-46
lines changed

2 files changed

+22
-46
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3599,12 +3599,16 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
35993599

36003600
// (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
36013601
if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
3602-
if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A))))
3602+
if (match(Op1,
3603+
m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
3604+
match(Op1, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
36033605
return BinaryOperator::CreateOr(Op0, C);
36043606

3605-
// ((A ^ C) ^ B) | (B ^ A) -> (B ^ A) | C
3606-
if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))))
3607-
if (match(Op1, m_Xor(m_Specific(B), m_Specific(A))))
3607+
// ((B ^ C) ^ A) | (A ^ B) -> (A ^ B) | C
3608+
if (match(Op1, m_Xor(m_Value(A), m_Value(B))))
3609+
if (match(Op0,
3610+
m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
3611+
match(Op0, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
36083612
return BinaryOperator::CreateOr(Op1, C);
36093613

36103614
if (Instruction *DeMorgan = matchDeMorgansLaws(I, *this))

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

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,9 +1194,7 @@ define i32 @or_xor_tree_0001(i32 %ax, i32 %bx, i32 %cx) {
11941194
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
11951195
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
11961196
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1197-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1198-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1199-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1197+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
12001198
; CHECK-NEXT: ret i32 [[OR]]
12011199
;
12021200
%a = mul i32 %ax, 42
@@ -1215,9 +1213,7 @@ define i32 @or_xor_tree_0010(i32 %ax, i32 %bx, i32 %cx) {
12151213
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
12161214
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
12171215
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1218-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1219-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1220-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1216+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
12211217
; CHECK-NEXT: ret i32 [[OR]]
12221218
;
12231219
%a = mul i32 %ax, 42
@@ -1236,9 +1232,7 @@ define i32 @or_xor_tree_0011(i32 %ax, i32 %bx, i32 %cx) {
12361232
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
12371233
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
12381234
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1239-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1240-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1241-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1235+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
12421236
; CHECK-NEXT: ret i32 [[OR]]
12431237
;
12441238
%a = mul i32 %ax, 42
@@ -1257,9 +1251,7 @@ define i32 @or_xor_tree_0100(i32 %ax, i32 %bx, i32 %cx) {
12571251
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
12581252
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
12591253
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1260-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1261-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1262-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1254+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
12631255
; CHECK-NEXT: ret i32 [[OR]]
12641256
;
12651257
%a = mul i32 %ax, 42
@@ -1278,9 +1270,7 @@ define i32 @or_xor_tree_0101(i32 %ax, i32 %bx, i32 %cx) {
12781270
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
12791271
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
12801272
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1281-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1282-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1283-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1273+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
12841274
; CHECK-NEXT: ret i32 [[OR]]
12851275
;
12861276
%a = mul i32 %ax, 42
@@ -1299,9 +1289,7 @@ define i32 @or_xor_tree_0110(i32 %ax, i32 %bx, i32 %cx) {
12991289
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
13001290
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
13011291
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1302-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1303-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1304-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1292+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
13051293
; CHECK-NEXT: ret i32 [[OR]]
13061294
;
13071295
%a = mul i32 %ax, 42
@@ -1320,9 +1308,7 @@ define i32 @or_xor_tree_0111(i32 %ax, i32 %bx, i32 %cx) {
13201308
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
13211309
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
13221310
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1323-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1324-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1325-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
1311+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
13261312
; CHECK-NEXT: ret i32 [[OR]]
13271313
;
13281314
%a = mul i32 %ax, 42
@@ -1360,9 +1346,7 @@ define i32 @or_xor_tree_1001(i32 %ax, i32 %bx, i32 %cx) {
13601346
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
13611347
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
13621348
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1363-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1364-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1365-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1349+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
13661350
; CHECK-NEXT: ret i32 [[OR]]
13671351
;
13681352
%a = mul i32 %ax, 42
@@ -1381,9 +1365,7 @@ define i32 @or_xor_tree_1010(i32 %ax, i32 %bx, i32 %cx) {
13811365
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
13821366
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
13831367
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1384-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1385-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1386-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1368+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
13871369
; CHECK-NEXT: ret i32 [[OR]]
13881370
;
13891371
%a = mul i32 %ax, 42
@@ -1402,9 +1384,7 @@ define i32 @or_xor_tree_1011(i32 %ax, i32 %bx, i32 %cx) {
14021384
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
14031385
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
14041386
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1405-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1406-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
1407-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1387+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
14081388
; CHECK-NEXT: ret i32 [[OR]]
14091389
;
14101390
%a = mul i32 %ax, 42
@@ -1423,9 +1403,7 @@ define i32 @or_xor_tree_1100(i32 %ax, i32 %bx, i32 %cx) {
14231403
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
14241404
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
14251405
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1426-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1427-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1428-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1406+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
14291407
; CHECK-NEXT: ret i32 [[OR]]
14301408
;
14311409
%a = mul i32 %ax, 42
@@ -1444,9 +1422,7 @@ define i32 @or_xor_tree_1101(i32 %ax, i32 %bx, i32 %cx) {
14441422
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
14451423
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
14461424
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1447-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
1448-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1449-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1425+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
14501426
; CHECK-NEXT: ret i32 [[OR]]
14511427
;
14521428
%a = mul i32 %ax, 42
@@ -1465,9 +1441,7 @@ define i32 @or_xor_tree_1110(i32 %ax, i32 %bx, i32 %cx) {
14651441
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
14661442
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
14671443
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
1468-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1469-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1470-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1444+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
14711445
; CHECK-NEXT: ret i32 [[OR]]
14721446
;
14731447
%a = mul i32 %ax, 42
@@ -1486,9 +1460,7 @@ define i32 @or_xor_tree_1111(i32 %ax, i32 %bx, i32 %cx) {
14861460
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
14871461
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
14881462
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
1489-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
1490-
; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
1491-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
1463+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
14921464
; CHECK-NEXT: ret i32 [[OR]]
14931465
;
14941466
%a = mul i32 %ax, 42

0 commit comments

Comments
 (0)