summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 7a8f2c27adc..9833bbc2a15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1295,8 +1295,9 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
// X urem Y -> X and Y-1, where Y is a power of 2,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ Type *Ty = I.getType();
if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
- Constant *N1 = Constant::getAllOnesValue(I.getType());
+ Constant *N1 = Constant::getAllOnesValue(Ty);
Value *Add = Builder.CreateAdd(Op1, N1);
return BinaryOperator::CreateAnd(Op0, Add);
}
@@ -1304,7 +1305,7 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
// 1 urem X -> zext(X != 1)
if (match(Op0, m_One())) {
Value *Cmp = Builder.CreateICmpNE(Op1, Op0);
- Value *Ext = Builder.CreateZExt(Cmp, I.getType());
+ Value *Ext = Builder.CreateZExt(Cmp, Ty);
return replaceInstUsesWith(I, Ext);
}
@@ -1315,6 +1316,16 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
return SelectInst::Create(Cmp, Op0, Sub);
}
+ // If the divisor is a sext of a boolean, then the divisor must be max
+ // unsigned value (-1). Therefore, the remainder is Op0 unless Op0 is also
+ // max unsigned value. In that case, the remainder is 0:
+ // urem Op0, (sext i1 X) --> (Op0 == -1) ? 0 : Op0
+ Value *X;
+ if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
+ Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
+ return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Op0);
+ }
+
return nullptr;
}
OpenPOWER on IntegriCloud