[llvm-commits] [SignlessTypes] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Reid Spencer
reid at x10sys.com
Sat Oct 21 18:37:08 PDT 2006
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.520.2.4 -> 1.520.2.5
---
Log message:
Fixes to get the DIV -> S/UDIV change working. This now passes MultiSource.
---
Diffs of the changes: (+157 -53)
InstructionCombining.cpp | 210 +++++++++++++++++++++++++++++++++++------------
1 files changed, 157 insertions(+), 53 deletions(-)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.4 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.5
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.4 Sat Oct 21 03:59:42 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Oct 21 20:36:52 2006
@@ -131,7 +131,8 @@
Instruction *visitAdd(BinaryOperator &I);
Instruction *visitSub(BinaryOperator &I);
Instruction *visitMul(BinaryOperator &I);
- Instruction *visitDiv(BinaryOperator &I);
+ Instruction *visitUDiv(BinaryOperator &I);
+ Instruction *visitSDiv(BinaryOperator &I);
Instruction *visitRem(BinaryOperator &I);
Instruction *visitAnd(BinaryOperator &I);
Instruction *visitOr (BinaryOperator &I);
@@ -1822,7 +1823,9 @@
return R;
}
- // add (cast *A to intptrtype) B -> cast (GEP (cast *A to sbyte*) B) -> intptrtype
+ // add (cast *A to intptrtype) B ->
+ // cast (GEP (cast *A to sbyte*) B) ->
+ // intptrtype
{
CastInst* CI = dyn_cast<CastInst>(LHS);
Value* Other = RHS;
@@ -1975,7 +1978,8 @@
}
// 0 - (X sdiv C) -> (X sdiv -C)
- if (Op1I->getOpcode() == Instruction::SDiv)
+ if (Op1I->getOpcode() == Instruction::SDiv ||
+ Op1I->getOpcode() == Instruction::UDiv)
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
if (CSI->isNullValue() && CSI->getType()->isSigned())
if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
@@ -2156,7 +2160,7 @@
return Changed ? &I : 0;
}
-Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
+Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (isa<UndefValue>(Op0)) // undef / X -> 0
@@ -2164,6 +2168,7 @@
if (isa<UndefValue>(Op1))
return ReplaceInstUsesWith(I, Op1); // X / undef -> undef
+ // If right hand side is a constant intger ..
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// div X, 1 == X
if (RHS->equalsInt(1))
@@ -2180,26 +2185,22 @@
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
return BinaryOperator::create(
Instruction::BinaryOps(LHS->getOpcode()), LHS->getOperand(0),
- ConstantExpr::getMul(RHS, LHSRHS),"");
+ ConstantExpr::getMul(RHS, LHSRHS));
}
// Check to see if this is an unsigned division with an exact power of 2,
// if so, convert to a right shift.
+ // X udiv C^2 -> X >> C
if (ConstantInt *C = dyn_cast<ConstantInt>(RHS))
- if (C->getType()->isUnsigned())
- if (uint64_t Val = C->getZExtValue()) // Don't break X / 0
- if (isPowerOf2_64(Val)) {
- uint64_t C = Log2_64(Val);
- return new ShiftInst(Instruction::Shr, Op0,
- ConstantInt::get(Type::UByteTy, C));
- }
-
- // -X/C -> X/-C
- if (RHS->getType()->isSigned())
- if (Value *LHSNeg = dyn_castNegVal(Op0))
- return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+ if (uint64_t Val = C->getZExtValue()) // Don't break X / 0
+ if (isPowerOf2_64(Val)) {
+ uint64_t C = Log2_64(Val);
+ return new ShiftInst(Instruction::Shr, Op0,
+ ConstantInt::get(Type::UByteTy, C));
+ }
- if (!RHS->isNullValue()) {
+
+ if (!RHS->isNullValue()) { // avoid X udiv 0
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
return R;
@@ -2268,41 +2269,22 @@
if (LHS->equalsInt(0))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- if (I.getType()->isSigned()) {
- // If the sign bits of both operands are zero (i.e. we can prove they are
- // unsigned inputs), turn this into a udiv.
- uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
- if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
- const Type *NTy = Op0->getType()->getUnsignedVersion();
- Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
- InsertNewInstBefore(LHS, I);
- Value *RHS;
- if (Constant *R = dyn_cast<Constant>(Op1))
- RHS = ConstantExpr::getCast(R, NTy);
- else
- RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
- Instruction *Div = BinaryOperator::createUDiv(LHS, RHS, I.getName());
- InsertNewInstBefore(Div, I);
- return new CastInst(Div, I.getType());
- }
- } else {
- // Known to be an unsigned division.
- if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
- // Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
- if (RHSI->getOpcode() == Instruction::Shl &&
- isa<ConstantInt>(RHSI->getOperand(0)) &&
- RHSI->getOperand(0)->getType()->isUnsigned()) {
- uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
- if (isPowerOf2_64(C1)) {
- uint64_t C2 = Log2_64(C1);
- Value *Add = RHSI->getOperand(1);
- if (C2) {
- Constant *C2V = ConstantInt::get(Add->getType(), C2);
- Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
- "tmp"), I);
- }
- return new ShiftInst(Instruction::Shr, Op0, Add);
+ // Known to be an unsigned division.
+ if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
+ // Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
+ if (RHSI->getOpcode() == Instruction::Shl &&
+ isa<ConstantInt>(RHSI->getOperand(0)) &&
+ RHSI->getOperand(0)->getType()->isUnsigned()) {
+ uint64_t C1 = cast<ConstantInt>(RHSI->getOperand(0))->getZExtValue();
+ if (isPowerOf2_64(C1)) {
+ uint64_t C2 = Log2_64(C1);
+ Value *Add = RHSI->getOperand(1);
+ if (C2) {
+ Constant *C2V = ConstantInt::get(Add->getType(), C2);
+ Add = InsertNewInstBefore(BinaryOperator::createAdd(Add, C2V,
+ "tmp"), I);
}
+ return new ShiftInst(Instruction::Shr, Op0, Add);
}
}
}
@@ -2310,6 +2292,128 @@
return 0;
}
+Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (isa<UndefValue>(Op0)) // undef / X -> 0
+ return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+ if (isa<UndefValue>(Op1))
+ return ReplaceInstUsesWith(I, Op1); // X / undef -> undef
+
+ if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+ // div X, 1 == X
+ if (RHS->equalsInt(1))
+ return ReplaceInstUsesWith(I, Op0);
+
+ // div X, -1 == -X
+ if (RHS->isAllOnesValue())
+ return BinaryOperator::createNeg(Op0);
+
+ // (X / C1) / C2 -> X / (C1*C2)
+ if (Instruction *LHS = dyn_cast<Instruction>(Op0))
+ if (LHS->getOpcode() == Instruction::SDiv ||
+ LHS->getOpcode()==Instruction::UDiv)
+ if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
+ return BinaryOperator::create(
+ Instruction::BinaryOps(LHS->getOpcode()), LHS->getOperand(0),
+ ConstantExpr::getMul(RHS, LHSRHS));
+ }
+
+ // -X/C -> X/-C
+ if (Value *LHSNeg = dyn_castNegVal(Op0))
+ return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+
+ if (!RHS->isNullValue()) {
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+ if (Instruction *R = FoldOpIntoSelect(I, SI, this))
+ return R;
+ if (isa<PHINode>(Op0))
+ if (Instruction *NV = FoldOpIntoPhi(I))
+ return NV;
+ }
+ }
+
+ // Handle div X, Cond?Y:Z
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+ // div X, (Cond ? 0 : Y) -> div X, Y. If the div and the select are in the
+ // same basic block, then we replace the select with Y, and the condition of
+ // the select with false (if the cond value is in the same BB). If the
+ // select has uses other than the div, this allows them to be simplified
+ // also.
+ if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
+ if (ST->isNullValue()) {
+ Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+ if (CondI && CondI->getParent() == I.getParent())
+ UpdateValueUsesWith(CondI, ConstantBool::getFalse());
+ else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+ I.setOperand(1, SI->getOperand(2));
+ else
+ UpdateValueUsesWith(SI, SI->getOperand(2));
+ return &I;
+ }
+ // Likewise for: div X, (Cond ? Y : 0) -> div X, Y
+ if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
+ if (ST->isNullValue()) {
+ Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
+ if (CondI && CondI->getParent() == I.getParent())
+ UpdateValueUsesWith(CondI, ConstantBool::getTrue());
+ else if (I.getParent() != SI->getParent() || SI->hasOneUse())
+ I.setOperand(1, SI->getOperand(1));
+ else
+ UpdateValueUsesWith(SI, SI->getOperand(1));
+ return &I;
+ }
+
+ // If this is 'udiv X, (Cond ? C1, C2)' where C1&C2 are powers of two,
+ // transform this into: '(Cond ? (udiv X, C1) : (udiv X, C2))'.
+ if (ConstantInt *STO = dyn_cast<ConstantInt>(SI->getOperand(1)))
+ if (ConstantInt *SFO = dyn_cast<ConstantInt>(SI->getOperand(2)))
+ if (STO->getType()->isUnsigned() && SFO->getType()->isUnsigned()) {
+ // STO == 0 and SFO == 0 handled above.
+ uint64_t TVA = STO->getZExtValue(), FVA = SFO->getZExtValue();
+ if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
+ unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
+ Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
+ Instruction *TSI = new ShiftInst(Instruction::Shr, Op0,
+ TC, SI->getName()+".t");
+ TSI = InsertNewInstBefore(TSI, I);
+
+ Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
+ Instruction *FSI = new ShiftInst(Instruction::Shr, Op0,
+ FC, SI->getName()+".f");
+ FSI = InsertNewInstBefore(FSI, I);
+ return new SelectInst(SI->getOperand(0), TSI, FSI);
+ }
+ }
+ }
+
+ // 0 / X == 0, we don't need to preserve faults!
+ if (ConstantInt *LHS = dyn_cast<ConstantInt>(Op0))
+ if (LHS->equalsInt(0))
+ return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+
+ // Known to be signed div
+
+ // If the sign bits of both operands are zero (i.e. we can prove they are
+ // unsigned inputs), turn this into a udiv.
+ uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1);
+ if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) {
+ const Type *NTy = Op0->getType()->getUnsignedVersion();
+ Instruction *LHS = new CastInst(Op0, NTy, Op0->getName());
+ InsertNewInstBefore(LHS, I);
+ Value *RHS;
+ if (Constant *R = dyn_cast<Constant>(Op1))
+ RHS = ConstantExpr::getCast(R, NTy);
+ else
+ RHS = InsertNewInstBefore(new CastInst(Op1, NTy, Op1->getName()), I);
+ Instruction *Div = BinaryOperator::createUDiv(LHS, RHS, I.getName());
+ InsertNewInstBefore(Div, I);
+ return new CastInst(Div, I.getType());
+ }
+
+ return 0;
+}
+
/// GetFactor - If we can prove that the specified value is at least a multiple
/// of some factor, return that factor.
@@ -4901,7 +5005,7 @@
// shr int -1, X = -1 (for any arithmetic shift rights of ~0)
if (!isLeftShift)
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
- if (CSI->isAllOnesValue())
+ if (CSI->isAllOnesValue() && Op0->getType()->isSigned())
return ReplaceInstUsesWith(I, CSI);
// Try to fold constant and into select arguments.
More information about the llvm-commits
mailing list