diff options
| author | Benjamin Kramer <benny.kra@googlemail.com> | 2011-04-01 20:09:10 +0000 |
|---|---|---|
| committer | Benjamin Kramer <benny.kra@googlemail.com> | 2011-04-01 20:09:10 +0000 |
| commit | d121765e6452c11ce17714feb2caa2d154d5e22b (patch) | |
| tree | 53decde5ec547162a6d5989642448dc513cb5cc9 /llvm/lib/Transforms/InstCombine | |
| parent | 398b8c5faff9ea9aa7adc586d2b52e0e1ce16fde (diff) | |
| download | bcm5719-llvm-d121765e6452c11ce17714feb2caa2d154d5e22b.tar.gz bcm5719-llvm-d121765e6452c11ce17714feb2caa2d154d5e22b.zip | |
InstCombine: Turn icmp + sext into bitwise/integer ops when the input has only one unknown bit.
int test1(unsigned x) { return (x&8) ? 0 : -1; }
int test3(unsigned x) { return (x&8) ? -1 : 0; }
before (x86_64):
_test1:
andl $8, %edi
cmpl $1, %edi
sbbl %eax, %eax
ret
_test3:
andl $8, %edi
cmpl $1, %edi
sbbl %eax, %eax
notl %eax
ret
after:
_test1:
shrl $3, %edi
andl $1, %edi
leal -1(%rdi), %eax
ret
_test3:
shll $28, %edi
movl %edi, %eax
sarl $31, %eax
ret
llvm-svn: 128732
Diffstat (limited to 'llvm/lib/Transforms/InstCombine')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 0401fb2d69d..d2ab61845f2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -882,6 +882,10 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) { Value *Op0 = ICI->getOperand(0), *Op1 = ICI->getOperand(1); ICmpInst::Predicate Pred = ICI->getPredicate(); + // Transforming icmps with more than one use is not profitable. + if (!ICI->hasOneUse()) + return 0; + if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) { // (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed // (x >s -1) ? -1 : 0 -> ashr x, 31 -> all ones if not signed @@ -898,6 +902,52 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) { In = Builder->CreateNot(In, In->getName()+".not"); return ReplaceInstUsesWith(CI, In); } + + // If we know that only one bit of the LHS of the icmp can be set and we + // have an equality comparison with zero or a power of 2, we can transform + // the icmp and sext into bitwise/integer operations. + if (ICI->isEquality() && (Op1C->isZero() || Op1C->getValue().isPowerOf2())){ + unsigned BitWidth = Op1C->getType()->getBitWidth(); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + APInt TypeMask(APInt::getAllOnesValue(BitWidth)); + ComputeMaskedBits(Op0, TypeMask, KnownZero, KnownOne); + + if ((~KnownZero).isPowerOf2()) { + Value *In = ICI->getOperand(0); + + if (!Op1C->isZero() == (Pred == ICmpInst::ICMP_NE)) { + // sext ((x & 2^n) == 0) -> (x >> n) - 1 + // sext ((x & 2^n) != 2^n) -> (x >> n) - 1 + unsigned ShiftAmt = KnownZeroMask.countTrailingZeros(); + // Perform a right shift to place the desired bit in the LSB. + if (ShiftAmt) + In = Builder->CreateLShr(In, + ConstantInt::get(In->getType(), ShiftAmt)); + + // At this point "In" is either 1 or 0. Subtract 1 to turn + // {1, 0} -> {0, -1}. + In = Builder->CreateAdd(In, + ConstantInt::getAllOnesValue(In->getType()), + "sext"); + } else { + // sext ((x & 2^n) != 0) -> (x << bitwidth-n) a>> bitwidth-1 + // sext ((x & 2^n) != 2^n) -> (x << bitwidth-n) a>> bitwidth-1 + unsigned ShiftAmt = KnownZeroMask.countLeadingZeros(); + // Perform a left shift to place the desired bit in the MSB. + if (ShiftAmt) + In = Builder->CreateShl(In, + ConstantInt::get(In->getType(), ShiftAmt)); + + // Distribute the bit over the whole bit width. + In = Builder->CreateAShr(In, ConstantInt::get(In->getType(), + BitWidth - 1), "sext"); + } + + if (CI.getType() == In->getType()) + return ReplaceInstUsesWith(CI, In); + return CastInst::CreateIntegerCast(In, CI.getType(), true/*SExt*/); + } + } } // vector (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed. |

