Author: Roman Lebedev Date: 2021-01-22T17:23:54+03:00 New Revision: d1a6f92fd545726aab0784e2dcfb193ce185c418
URL: https://github.com/llvm/llvm-project/commit/d1a6f92fd545726aab0784e2dcfb193ce185c418 DIFF: https://github.com/llvm/llvm-project/commit/d1a6f92fd545726aab0784e2dcfb193ce185c418.diff LOG: [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. Added: Modified: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp llvm/lib/Transforms/InstCombine/InstCombineInternal.h llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll Removed: ################################################################################ diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 944e7c4b1325..68c4156af2c4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1984,7 +1984,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) { } // (~x) & y --> ~(x | (~y)) iff that gets rid of inversions - if (sinkNotIntoOtherHandOfAnd(I)) + if (sinkNotIntoOtherHandOfAndOrOr(I)) return &I; return nullptr; @@ -2867,6 +2867,10 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) { } } + // (~x) | y --> ~(x & (~y)) iff that gets rid of inversions + if (sinkNotIntoOtherHandOfAndOrOr(I)) + return &I; + return nullptr; } @@ -3094,16 +3098,19 @@ static Instruction *sinkNotIntoXor(BinaryOperator &I, } // Transform -// z = (~x) & y +// z = (~x) &/| y // into: -// z = ~(x | (~y)) +// z = ~(x |/& (~y)) // iff y is free to invert and all uses of z can be freely updated. -bool InstCombinerImpl::sinkNotIntoOtherHandOfAnd(BinaryOperator &I) { +bool InstCombinerImpl::sinkNotIntoOtherHandOfAndOrOr(BinaryOperator &I) { Instruction::BinaryOps NewOpc; switch (I.getOpcode()) { case Instruction::And: NewOpc = Instruction::Or; break; + case Instruction::Or: + NewOpc = Instruction::And; + break; default: return false; }; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index c56b31bd227b..5e466c5e13e7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -105,7 +105,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted); Instruction *visitAnd(BinaryOperator &I); Instruction *visitOr(BinaryOperator &I); - bool sinkNotIntoOtherHandOfAnd(BinaryOperator &I); + bool sinkNotIntoOtherHandOfAndOrOr(BinaryOperator &I); Instruction *visitXor(BinaryOperator &I); Instruction *visitShl(BinaryOperator &I); Value *reassociateShiftAmtsOfTwoSameDirectionShifts( diff --git a/llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll b/llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll index 57ef48725ead..d40acc37ca73 100644 --- a/llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll +++ b/llvm/test/Transforms/InstCombine/sink-not-into-another-hand-of-or.ll @@ -12,10 +12,9 @@ declare void @use1(i1) ; Most basic positive test define i32 @t0(i1 %i0, i32 %v0, i32 %v1, i32 %v2, i32 %v3) { ; CHECK-LABEL: @t0( -; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]] -; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0:%.*]], true -; CHECK-NEXT: [[I3:%.*]] = or i1 [[I1]], [[I2]] -; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i32 [[V2:%.*]], i32 [[V3:%.*]] +; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[I1]], [[I0:%.*]] +; CHECK-NEXT: [[I4:%.*]] = select i1 [[TMP1]], i32 [[V3:%.*]], i32 [[V2:%.*]] ; CHECK-NEXT: ret i32 [[I4]] ; %i1 = icmp eq i32 %v0, %v1 @@ -27,11 +26,10 @@ define i32 @t0(i1 %i0, i32 %v0, i32 %v1, i32 %v2, i32 %v3) { define i32 @t1(i32 %v0, i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5) { ; CHECK-LABEL: @t1( ; CHECK-NEXT: [[I0:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]] -; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] +; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] ; CHECK-NEXT: call void @use1(i1 [[I0]]) -; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0]], true -; CHECK-NEXT: [[I3:%.*]] = or i1 [[I1]], [[I2]] -; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i32 [[V4:%.*]], i32 [[V5:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[I0]], [[I1]] +; CHECK-NEXT: [[I4:%.*]] = select i1 [[TMP1]], i32 [[V5:%.*]], i32 [[V4:%.*]] ; CHECK-NEXT: ret i32 [[I4]] ; %i0 = icmp eq i32 %v0, %v1 diff --git a/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll b/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll index 3736a1d03677..921d26387aa2 100644 --- a/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll +++ b/llvm/test/Transforms/SimplifyCFG/merge-cond-stores.ll @@ -5,14 +5,12 @@ define void @test_simple(i32* %p, i32 %a, i32 %b) { ; CHECK-LABEL: @test_simple( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0 -; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X2]], true -; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]] -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP3:%.*]], label [[TMP2:%.*]] ; CHECK: 2: -; CHECK-NEXT: [[NOT_X2:%.*]] = xor i1 [[X2]], true -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32 +; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 ; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4 ; CHECK-NEXT: br label [[TMP3]] ; CHECK: 3: @@ -78,21 +76,20 @@ define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) { ; CHECK-LABEL: @test_recursive( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[X4:%.*]] = icmp eq i32 [[D:%.*]], 0 ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[X4]], true -; CHECK-NEXT: [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]] -; CHECK-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]] -; CHECK: 5: +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[D:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; CHECK: 4: +; CHECK-NEXT: [[X4:%.*]] = icmp eq i32 [[D]], 0 ; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C]], 0 ; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 ; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[X3]], i32 [[SPEC_SELECT]], i32 2 ; CHECK-NEXT: [[SPEC_SELECT2:%.*]] = select i1 [[X4]], i32 [[SPEC_SELECT1]], i32 3 ; CHECK-NEXT: store i32 [[SPEC_SELECT2]], i32* [[P:%.*]], align 4 -; CHECK-NEXT: br label [[TMP6]] -; CHECK: 6: +; CHECK-NEXT: br label [[TMP5]] +; CHECK: 5: ; CHECK-NEXT: ret void ; entry: @@ -383,14 +380,12 @@ define void @test_outer_if(i32* %p, i32 %a, i32 %b, i32 %c) { ; CHECK-NEXT: [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0 ; CHECK-NEXT: br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]] ; CHECK: continue: -; CHECK-NEXT: [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0 -; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X2]], true -; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]] -; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[END]] +; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP1]], label [[END]], label [[TMP2:%.*]] ; CHECK: 2: -; CHECK-NEXT: [[NOT_X2:%.*]] = xor i1 [[X2]], true -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32 +; CHECK-NEXT: [[X2:%.*]] = icmp ne i32 [[B]], 0 +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32 ; CHECK-NEXT: store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4 ; CHECK-NEXT: br label [[END]] ; CHECK: end: _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits