Skip to content

Commit d1a6f92

Browse files
committed
[InstCombine] Fold (~x) | y --> ~(x & (~y)) iff it is free to do so
Iff we know we can get rid of the inversions in the new pattern, we can thus get rid of the inversion in the old pattern, this decreasing instruction count. Note that we could position this transformation as just hoisting of the `not` (still, iff y is freely negatible), but the test changes show a number of regressions, so let's not do that.
1 parent 79b0d21 commit d1a6f92

File tree

4 files changed

+35
-35
lines changed

4 files changed

+35
-35
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
19841984
}
19851985

19861986
// (~x) & y --> ~(x | (~y)) iff that gets rid of inversions
1987-
if (sinkNotIntoOtherHandOfAnd(I))
1987+
if (sinkNotIntoOtherHandOfAndOrOr(I))
19881988
return &I;
19891989

19901990
return nullptr;
@@ -2867,6 +2867,10 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
28672867
}
28682868
}
28692869

2870+
// (~x) | y --> ~(x & (~y)) iff that gets rid of inversions
2871+
if (sinkNotIntoOtherHandOfAndOrOr(I))
2872+
return &I;
2873+
28702874
return nullptr;
28712875
}
28722876

@@ -3094,16 +3098,19 @@ static Instruction *sinkNotIntoXor(BinaryOperator &I,
30943098
}
30953099

30963100
// Transform
3097-
// z = (~x) & y
3101+
// z = (~x) &/| y
30983102
// into:
3099-
// z = ~(x | (~y))
3103+
// z = ~(x |/& (~y))
31003104
// iff y is free to invert and all uses of z can be freely updated.
3101-
bool InstCombinerImpl::sinkNotIntoOtherHandOfAnd(BinaryOperator &I) {
3105+
bool InstCombinerImpl::sinkNotIntoOtherHandOfAndOrOr(BinaryOperator &I) {
31023106
Instruction::BinaryOps NewOpc;
31033107
switch (I.getOpcode()) {
31043108
case Instruction::And:
31053109
NewOpc = Instruction::Or;
31063110
break;
3111+
case Instruction::Or:
3112+
NewOpc = Instruction::And;
3113+
break;
31073114
default:
31083115
return false;
31093116
};

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
105105
Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted);
106106
Instruction *visitAnd(BinaryOperator &I);
107107
Instruction *visitOr(BinaryOperator &I);
108-
bool sinkNotIntoOtherHandOfAnd(BinaryOperator &I);
108+
bool sinkNotIntoOtherHandOfAndOrOr(BinaryOperator &I);
109109
Instruction *visitXor(BinaryOperator &I);
110110
Instruction *visitShl(BinaryOperator &I);
111111
Value *reassociateShiftAmtsOfTwoSameDirectionShifts(

llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ declare void @use1(i1)
1212
; Most basic positive test
1313
define i32 @t0(i1 %i0, i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
1414
; CHECK-LABEL: @t0(
15-
; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
16-
; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0:%.*]], true
17-
; CHECK-NEXT: [[I3:%.*]] = or i1 [[I1]], [[I2]]
18-
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i32 [[V2:%.*]], i32 [[V3:%.*]]
15+
; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
16+
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[I1]], [[I0:%.*]]
17+
; CHECK-NEXT: [[I4:%.*]] = select i1 [[TMP1]], i32 [[V3:%.*]], i32 [[V2:%.*]]
1918
; CHECK-NEXT: ret i32 [[I4]]
2019
;
2120
%i1 = icmp eq i32 %v0, %v1
@@ -27,11 +26,10 @@ define i32 @t0(i1 %i0, i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
2726
define i32 @t1(i32 %v0, i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5) {
2827
; CHECK-LABEL: @t1(
2928
; CHECK-NEXT: [[I0:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
30-
; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
29+
; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
3130
; CHECK-NEXT: call void @use1(i1 [[I0]])
32-
; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0]], true
33-
; CHECK-NEXT: [[I3:%.*]] = or i1 [[I1]], [[I2]]
34-
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i32 [[V4:%.*]], i32 [[V5:%.*]]
31+
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[I0]], [[I1]]
32+
; CHECK-NEXT: [[I4:%.*]] = select i1 [[TMP1]], i32 [[V5:%.*]], i32 [[V4:%.*]]
3533
; CHECK-NEXT: ret i32 [[I4]]
3634
;
3735
%i0 = icmp eq i32 %v0, %v1

llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
define void @test_simple(i32* %p, i32 %a, i32 %b) {
66
; CHECK-LABEL: @test_simple(
77
; CHECK-NEXT: entry:
8-
; CHECK-NEXT: [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0
9-
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
10-
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X2]], true
11-
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]]
12-
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
8+
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
9+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
10+
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP3:%.*]], label [[TMP2:%.*]]
1311
; CHECK: 2:
14-
; CHECK-NEXT: [[NOT_X2:%.*]] = xor i1 [[X2]], true
15-
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32
12+
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
13+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
1614
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
1715
; CHECK-NEXT: br label [[TMP3]]
1816
; CHECK: 3:
@@ -78,21 +76,20 @@ define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
7876
; CHECK-LABEL: @test_recursive(
7977
; CHECK-NEXT: entry:
8078
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
81-
; CHECK-NEXT: [[X4:%.*]] = icmp eq i32 [[D:%.*]], 0
8279
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]]
83-
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
84-
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[X4]], true
85-
; CHECK-NEXT: [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]]
86-
; CHECK-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
87-
; CHECK: 5:
80+
; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[D:%.*]]
81+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
82+
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
83+
; CHECK: 4:
84+
; CHECK-NEXT: [[X4:%.*]] = icmp eq i32 [[D]], 0
8885
; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C]], 0
8986
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
9087
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
9188
; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[X3]], i32 [[SPEC_SELECT]], i32 2
9289
; CHECK-NEXT: [[SPEC_SELECT2:%.*]] = select i1 [[X4]], i32 [[SPEC_SELECT1]], i32 3
9390
; CHECK-NEXT: store i32 [[SPEC_SELECT2]], i32* [[P:%.*]], align 4
94-
; CHECK-NEXT: br label [[TMP6]]
95-
; CHECK: 6:
91+
; CHECK-NEXT: br label [[TMP5]]
92+
; CHECK: 5:
9693
; CHECK-NEXT: ret void
9794
;
9895
entry:
@@ -383,14 +380,12 @@ define void @test_outer_if(i32* %p, i32 %a, i32 %b, i32 %c) {
383380
; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
384381
; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
385382
; CHECK: continue:
386-
; CHECK-NEXT: [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0
387-
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
388-
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X2]], true
389-
; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]]
390-
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[END]]
383+
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
384+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
385+
; CHECK-NEXT: br i1 [[TMP1]], label [[END]], label [[TMP2:%.*]]
391386
; CHECK: 2:
392-
; CHECK-NEXT: [[NOT_X2:%.*]] = xor i1 [[X2]], true
393-
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32
387+
; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0
388+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
394389
; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
395390
; CHECK-NEXT: br label [[END]]
396391
; CHECK: end:

0 commit comments

Comments
 (0)