From: Sanjay Patel Date: Fri, 21 Apr 2017 14:03:54 +0000 (+0000) Subject: [InstCombine] prefer xor with -1 because 'not' is easier to understand (PR32706) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd1b03d467c2a5f96ccf612d9ae1c31a02a654ea;p=llvm [InstCombine] prefer xor with -1 because 'not' is easier to understand (PR32706) This matches the demanded bits behavior in the DAG and should fix: https://bugs.llvm.org/show_bug.cgi?id=32706 Differential Revision: https://reviews.llvm.org/D32255 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300977 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 2f6e411345f..d7e709c9cca 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -277,10 +277,20 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, return InsertNewInstWith(And, *I); } - // If the RHS is a constant, see if we can simplify it. - // FIXME: for XOR, we prefer to force bits to 1 if they will make a -1. - if (ShrinkDemandedConstant(I, 1, DemandedMask)) - return I; + // If the RHS is a constant, see if we can change it. Don't alter a -1 + // constant because that's a canonical 'not' op, and that is better for + // combining, SCEV, and codegen. + const APInt *C; + if (match(I->getOperand(1), m_APInt(C)) && !C->isAllOnesValue()) { + if ((*C | ~DemandedMask).isAllOnesValue()) { + // Force bits to 1 to create a 'not' op. + I->setOperand(1, ConstantInt::getAllOnesValue(VTy)); + return I; + } + // If we can't turn this into a 'not', try to shrink the constant. + if (ShrinkDemandedConstant(I, 1, DemandedMask)) + return I; + } // If our LHS is an 'and' and if it has one use, and if any of the bits we // are flipping are known to be set, then the xor is just resetting those diff --git a/test/Transforms/InstCombine/xor.ll b/test/Transforms/InstCombine/xor.ll index 570155b1623..33fe557ae5a 100644 --- a/test/Transforms/InstCombine/xor.ll +++ b/test/Transforms/InstCombine/xor.ll @@ -536,3 +536,20 @@ define i32 @test38(i32 %A, i32 %B) { %xor = xor i32 %and, %B ret i32 %xor } + +; PR32706 - https://bugs.llvm.org/show_bug.cgi?id=32706 +; Pin an xor constant operand to -1 if possible because 'not' is better for SCEV and codegen. + +define i32 @not_is_canonical(i32 %x, i32 %y) { +; CHECK-LABEL: @not_is_canonical( +; CHECK-NEXT: [[SUB:%.*]] = xor i32 %x, -1 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], %y +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[ADD]], 2 +; CHECK-NEXT: ret i32 [[MUL]] +; + %sub = xor i32 %x, 1073741823 + %add = add i32 %sub, %y + %mul = shl i32 %add, 2 + ret i32 %mul +} + diff --git a/test/Transforms/InstCombine/zext.ll b/test/Transforms/InstCombine/zext.ll index 887d839cb8c..d5c52bd811b 100644 --- a/test/Transforms/InstCombine/zext.ll +++ b/test/Transforms/InstCombine/zext.ll @@ -35,7 +35,7 @@ define <2 x i64> @test3(<2 x i64> %A) { define <2 x i64> @test4(<2 x i64> %A) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i64> %A, +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i64> %A, ; CHECK-NEXT: [[XOR:%.*]] = and <2 x i64> [[TMP1]], ; CHECK-NEXT: ret <2 x i64> [[XOR]] ;