From: Sanjay Patel Date: Tue, 2 May 2017 14:48:23 +0000 (+0000) Subject: revert r301923 : [InstCombine] don't use DeMorgan's Law on integer constants X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a30d9c6883dd2b853358e8e26627d22f9ccaba9e;p=llvm revert r301923 : [InstCombine] don't use DeMorgan's Law on integer constants There's a clang test that is wrongly using -O1 and failing after this commit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301924 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index c7092bf3a39..41ae37ee127 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2433,32 +2433,29 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { if (Value *V = SimplifyBSwap(I)) return replaceInstUsesWith(I, V); - // Apply DeMorgan's Law for 'nand' / 'nor' logic with an inverted operand. - Value *X, *Y; - - // We must eliminate the and/or (one-use) for these transforms to not increase - // the instruction count. - // ~(~X & Y) --> (X | ~Y) - // ~(Y & ~X) --> (X | ~Y) - if (match(&I, m_Not(m_OneUse(m_c_And(m_Not(m_Value(X)), m_Value(Y)))))) { - Value *NotY = Builder->CreateNot(Y, Y->getName() + ".not"); - return BinaryOperator::CreateOr(X, NotY); - } - // ~(~X | Y) --> (X & ~Y) - // ~(Y | ~X) --> (X & ~Y) - if (match(&I, m_Not(m_OneUse(m_c_Or(m_Not(m_Value(X)), m_Value(Y)))))) { - Value *NotY = Builder->CreateNot(Y, Y->getName() + ".not"); - return BinaryOperator::CreateAnd(X, NotY); - } - // Is this a 'not' (~) fed by a binary operator? BinaryOperator *NotOp; if (match(&I, m_Not(m_BinOp(NotOp)))) { if (NotOp->getOpcode() == Instruction::And || NotOp->getOpcode() == Instruction::Or) { - // Apply DeMorgan's Law when inverts are free: - // ~(X & Y) --> (~X | ~Y) - // ~(X | Y) --> (~X & ~Y) + // We must eliminate the and/or for this transform to not increase the + // instruction count. + if (NotOp->hasOneUse()) { + // ~(~X & Y) --> (X | ~Y) - De Morgan's Law + // ~(~X | Y) === (X & ~Y) - De Morgan's Law + if (dyn_castNotVal(NotOp->getOperand(1))) + NotOp->swapOperands(); + if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0))) { + Value *NotY = Builder->CreateNot( + NotOp->getOperand(1), NotOp->getOperand(1)->getName() + ".not"); + if (NotOp->getOpcode() == Instruction::And) + return BinaryOperator::CreateOr(Op0NotVal, NotY); + return BinaryOperator::CreateAnd(Op0NotVal, NotY); + } + } + + // ~(X & Y) --> (~X | ~Y) - De Morgan's Law + // ~(X | Y) === (~X & ~Y) - De Morgan's Law if (IsFreeToInvert(NotOp->getOperand(0), NotOp->getOperand(0)->hasOneUse()) && IsFreeToInvert(NotOp->getOperand(1), diff --git a/test/Transforms/InstCombine/assume2.ll b/test/Transforms/InstCombine/assume2.ll index 8dc8831fffa..e8fbc049f41 100644 --- a/test/Transforms/InstCombine/assume2.ll +++ b/test/Transforms/InstCombine/assume2.ll @@ -21,8 +21,8 @@ define i32 @test1(i32 %a) #0 { define i32 @test2(i32 %a) #0 { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 15 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 10 +; CHECK-NEXT: [[A_NOT:%.*]] = or i32 [[A:%.*]], -16 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A_NOT]], -6 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: ret i32 2 ; @@ -50,8 +50,8 @@ define i32 @test3(i32 %a) #0 { define i32 @test4(i32 %a) #0 { ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[V:%.*]] = or i32 [[A:%.*]], -16 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V]], -6 +; CHECK-NEXT: [[A_NOT:%.*]] = and i32 [[A:%.*]], 15 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A_NOT]], 10 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: ret i32 2 ; diff --git a/test/Transforms/InstCombine/demorgan.ll b/test/Transforms/InstCombine/demorgan.ll index 26c2270a3fd..fc4af3c6dad 100644 --- a/test/Transforms/InstCombine/demorgan.ll +++ b/test/Transforms/InstCombine/demorgan.ll @@ -367,12 +367,12 @@ define i8 @demorgan_nor_use2bc(i8 %A, i8 %B) { ret i8 %r2 } -; Do not apply DeMorgan's Law to constants. We prefer 'not' ops. +; FIXME: Do not apply DeMorgan's Law to constants. We prefer 'not' ops. define i32 @demorganize_constant1(i32 %a) { ; CHECK-LABEL: @demorganize_constant1( -; CHECK-NEXT: [[AND:%.*]] = and i32 %a, 15 -; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[AND]], -1 +; CHECK-NEXT: [[A_NOT:%.*]] = or i32 %a, -16 +; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], 15 ; CHECK-NEXT: ret i32 [[AND1]] ; %and = and i32 %a, 15 @@ -380,12 +380,12 @@ define i32 @demorganize_constant1(i32 %a) { ret i32 %and1 } -; Do not apply DeMorgan's Law to constants. We prefer 'not' ops. +; FIXME: Do not apply DeMorgan's Law to constants. We prefer 'not' ops. define i32 @demorganize_constant2(i32 %a) { ; CHECK-LABEL: @demorganize_constant2( -; CHECK-NEXT: [[AND:%.*]] = or i32 %a, 15 -; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[AND]], -1 +; CHECK-NEXT: [[A_NOT:%.*]] = and i32 %a, -16 +; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], -16 ; CHECK-NEXT: ret i32 [[AND1]] ; %and = or i32 %a, 15