diff options
| author | Shuxin Yang <shuxin.llvm@gmail.com> | 2012-11-26 21:44:25 +0000 |
|---|---|---|
| committer | Shuxin Yang <shuxin.llvm@gmail.com> | 2012-11-26 21:44:25 +0000 |
| commit | 6ea79e864d089d7795a03ecb30125cfcc7f06fff (patch) | |
| tree | 3db7168e9b5b90dd030e7023352d6fa00b544adc | |
| parent | b0916015aead352d441373db0c2ecbf06427a00d (diff) | |
| download | bcm5719-llvm-6ea79e864d089d7795a03ecb30125cfcc7f06fff.tar.gz bcm5719-llvm-6ea79e864d089d7795a03ecb30125cfcc7f06fff.zip | |
rdar://12329730 (defect 2)
Enhancement to InstCombine. Try to catch this opportunity:
---------------------------------------------------------------
((X^C1) >> C2) ^ C3 => (X>>C2) ^ ((C1>>C2)^C3)
where the subexpression "X ^ C1" has more than one uses, and
"(X^C1) >> C2" has single use.
----------------------------------------------------------------
Reviewed by Nadav (with minor change per his request).
llvm-svn: 168615
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/xor2.ll | 15 |
2 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 494cc7d1517..12faedb0ffe 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2159,6 +2159,27 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { I.setOperand(1, NewRHS); return &I; } + } else if (Op0I->getOpcode() == Instruction::LShr) { + // ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3) + // E1 = "X ^ C1" + BinaryOperator *E1; + ConstantInt *C1; + if (Op0I->hasOneUse() && + (E1 = dyn_cast<BinaryOperator>(Op0I->getOperand(0))) && + E1->getOpcode() == Instruction::Xor && + (C1 = dyn_cast<ConstantInt>(E1->getOperand(1)))) { + // fold (C1 >> C2) ^ C3 + ConstantInt *C2 = Op0CI, *C3 = RHS; + APInt FoldConst = C1->getValue().lshr(C2->getValue()); + FoldConst ^= C3->getValue(); + // Prepare the two operands. + Value *Opnd0 = Builder->CreateLShr(E1->getOperand(0), C2); + Opnd0->takeName(Op0I); + cast<Instruction>(Opnd0)->setDebugLoc(I.getDebugLoc()); + Value *FoldVal = ConstantInt::get(Opnd0->getType(), FoldConst); + + return BinaryOperator::CreateXor(Opnd0, FoldVal); + } } } } diff --git a/llvm/test/Transforms/InstCombine/xor2.ll b/llvm/test/Transforms/InstCombine/xor2.ll index 89f00bd6847..3c992467967 100644 --- a/llvm/test/Transforms/InstCombine/xor2.ll +++ b/llvm/test/Transforms/InstCombine/xor2.ll @@ -51,3 +51,18 @@ define i32 @test4(i32 %A, i32 %B) { ; CHECK: %1 = ashr i32 %A, %B ; CHECK: ret i32 %1 } + +; defect-2 in rdar://12329730 +; (X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3) +; where the "X" has more than one use +define i32 @test5(i32 %val1) { +test5: + %xor = xor i32 %val1, 1234 + %shr = lshr i32 %xor, 8 + %xor1 = xor i32 %shr, 1 + %add = add i32 %xor1, %xor + ret i32 %add +; CHECK: @test5 +; CHECK: lshr i32 %val1, 8 +; CHECK: ret +} |

