Skip to content

Commit 1e274f3

Browse files
chenglin.bifengfeng09
authored andcommitted
[InstCombine] Add pattern 'if (C1 & C2) == C2 then (X & C1) - (X & C2) -> X & (C1 ^ C2)'
https://alive2.llvm.org/ce/z/BveKM5
1 parent 33ca979 commit 1e274f3

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,16 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
22802280
if (match(Op0, m_OneUse(m_Add(m_Value(X), m_AllOnes()))))
22812281
return BinaryOperator::CreateAdd(Builder.CreateNot(Op1), X);
22822282

2283+
// if (C1 & C2) == C2 then (X & C1) - (X & C2) -> X & (C1 ^ C2)
2284+
Constant *C1, *C2;
2285+
if (match(Op0, m_And(m_Value(X), m_ImmConstant(C1))) &&
2286+
match(Op1, m_And(m_Specific(X), m_ImmConstant(C2)))) {
2287+
Value *AndC = ConstantFoldBinaryInstruction(Instruction::And, C1, C2);
2288+
if (C2->isElementWiseEqual(AndC))
2289+
return BinaryOperator::CreateAnd(
2290+
X, ConstantFoldBinaryInstruction(Instruction::Xor, C1, C2));
2291+
}
2292+
22832293
// Reassociate sub/add sequences to create more add instructions and
22842294
// reduce dependency chains:
22852295
// ((X - Y) + Z) - Op1 --> (X + Z) - (Y + Op1)

llvm/test/Transforms/InstCombine/and-sub-combine.ll

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
define i8 @and_sub(i8 %a) {
55
; CHECK-LABEL: @and_sub(
6-
; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], 15
7-
; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], 3
8-
; CHECK-NEXT: [[RET:%.*]] = sub nsw i8 [[AND1]], [[AND2]]
6+
; CHECK-NEXT: [[RET:%.*]] = and i8 [[A:%.*]], 12
97
; CHECK-NEXT: ret i8 [[RET]]
108
;
119
%and1 = and i8 %a, 15
@@ -22,7 +20,7 @@ define i8 @and_sub_multi_use(i8 %a) {
2220
; CHECK-NEXT: call void @use(i8 [[AND1]])
2321
; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], 3
2422
; CHECK-NEXT: call void @use(i8 [[AND2]])
25-
; CHECK-NEXT: [[RET:%.*]] = sub nsw i8 [[AND1]], [[AND2]]
23+
; CHECK-NEXT: [[RET:%.*]] = and i8 [[A]], 12
2624
; CHECK-NEXT: ret i8 [[RET]]
2725
;
2826
%and1 = and i8 %a, 15
@@ -35,9 +33,7 @@ define i8 @and_sub_multi_use(i8 %a) {
3533

3634
define <2 x i32> @and_sub_vec(<2 x i32> %a) {
3735
; CHECK-LABEL: @and_sub_vec(
38-
; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[A:%.*]], <i32 11, i32 10>
39-
; CHECK-NEXT: [[AND2:%.*]] = and <2 x i32> [[A]], <i32 8, i32 2>
40-
; CHECK-NEXT: [[RET:%.*]] = sub nsw <2 x i32> [[AND1]], [[AND2]]
36+
; CHECK-NEXT: [[RET:%.*]] = and <2 x i32> [[A:%.*]], <i32 3, i32 8>
4137
; CHECK-NEXT: ret <2 x i32> [[RET]]
4238
;
4339
%and1 = and <2 x i32> %a, <i32 11, i32 10>
@@ -49,10 +45,7 @@ define <2 x i32> @and_sub_vec(<2 x i32> %a) {
4945

5046
define <2 x i32> @and_sub_vec_posion(<2 x i32> %a) {
5147
; CHECK-LABEL: @and_sub_vec_posion(
52-
; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[A:%.*]], <i32 11, i32 poison>
53-
; CHECK-NEXT: [[AND2:%.*]] = and <2 x i32> [[A]], <i32 poison, i32 2>
54-
; CHECK-NEXT: [[RET:%.*]] = sub nsw <2 x i32> [[AND1]], [[AND2]]
55-
; CHECK-NEXT: ret <2 x i32> [[RET]]
48+
; CHECK-NEXT: ret <2 x i32> poison
5649
;
5750
%and1 = and <2 x i32> %a, <i32 11, i32 poison>
5851
%and2 = and <2 x i32> %a, <i32 poison, i32 2>

0 commit comments

Comments
 (0)