summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2010-11-23 18:52:42 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2010-11-23 18:52:42 +0000
commitb5afa65b0a426ef8ce7b4602952b5c3b106071e7 (patch)
tree19b8f73545bb7dbdbfc2c625bd1f119edcd0be1d /llvm/lib/Transforms
parente3120ed1bfc0b8163186732efce14f3b5d9ecf5f (diff)
downloadbcm5719-llvm-b5afa65b0a426ef8ce7b4602952b5c3b106071e7.tar.gz
bcm5719-llvm-b5afa65b0a426ef8ce7b4602952b5c3b106071e7.zip
InstCombine: Reduce "X shift (A srem B)" to "X shift (A urem B)" iff B is positive.
This allows to transform the rem in "1 << ((int)x % 8);" to an and. llvm-svn: 120028
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp15
1 files changed, 15 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9f7d98ed794..7969dbfec04 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -53,6 +53,21 @@ Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
if (ConstantInt *CUI = dyn_cast<ConstantInt>(Op1))
if (Instruction *Res = FoldShiftByConstant(Op0, CUI, I))
return Res;
+
+ // X shift (A srem B) -> X shift (A urem B) iff B is positive.
+ // Because shifts by negative values are undefined.
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op1))
+ if (BO->getOpcode() == Instruction::SRem && BO->getType()->isIntegerTy()) {
+ // Make sure the divisor's sign bit is zero.
+ APInt Mask = APInt::getSignBit(BO->getType()->getPrimitiveSizeInBits());
+ if (MaskedValueIsZero(BO->getOperand(1), Mask)) {
+ Value *URem = Builder->CreateURem(BO->getOperand(0), BO->getOperand(1),
+ BO->getName());
+ I.setOperand(1, URem);
+ return &I;
+ }
+ }
+
return 0;
}
OpenPOWER on IntegriCloud