[llvm-commits] [SignlessTypes] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Reid Spencer
reid at x10sys.com
Wed Oct 25 18:58:37 PDT 2006
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.520.2.9 -> 1.520.2.10
---
Log message:
Round 2 of DIV updates.
---
Diffs of the changes: (+185 -165)
InstructionCombining.cpp | 350 ++++++++++++++++++++++++-----------------------
1 files changed, 185 insertions(+), 165 deletions(-)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.9 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.10
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.520.2.9 Mon Oct 23 13:13:27 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Oct 25 20:58:05 2006
@@ -1987,7 +1987,7 @@
// 0 - (X sdiv C) -> (X sdiv -C)
if (Op1I->getOpcode() == Instruction::SDiv)
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0))
- if (CSI->getType()->isSigned() && CSI->isNullValue())
+ if (CSI->isNullValue())
if (Constant *DivRHS = dyn_cast<Constant>(Op1I->getOperand(1)))
return BinaryOperator::createSDiv(Op1I->getOperand(0),
ConstantExpr::getNeg(DivRHS));
@@ -2169,53 +2169,21 @@
Instruction* InstCombiner::commonDivTransforms(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- if (isa<UndefValue>(Op0)) // undef / X -> 0
+ // undef / X -> 0
+ if (isa<UndefValue>(Op0))
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- if (isa<UndefValue>(Op1))
- return ReplaceInstUsesWith(I, Op1); // X / undef -> undef
- return 0;
-}
-
-Instruction* InstCombiner::commonIDivTransforms(BinaryOperator &I) {
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
- 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 ||
- LHS->getOpcode()==Instruction::FDiv)
- if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
- return BinaryOperator::create(
- Instruction::BinaryOps(LHS->getOpcode()), LHS->getOperand(0),
- ConstantExpr::getMul(RHS, LHSRHS));
- }
- if (!RHS->isNullValue()) { // avoid X udiv 0
- 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;
- }
- }
+ // X / undef -> undef
+ if (isa<UndefValue>(Op1))
+ return ReplaceInstUsesWith(I, Op1);
- // Handle div X, Cond?Y:Z
+ // Handle cases involving: div X, (select 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
+ // 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.
+ // also. Note that div X, Y is just as good as div X, 0 (undef)
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
if (ST->isNullValue()) {
Instruction *CondI = dyn_cast<Instruction>(SI->getOperand(0));
@@ -2227,6 +2195,7 @@
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()) {
@@ -2239,28 +2208,38 @@
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);
- }
+ return 0;
+}
+
+Instruction* InstCombiner::commonIDivTransforms(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (Instruction *Common = commonDivTransforms(I))
+ return Common;
+
+ if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+ // div X, 1 == X
+ if (RHS->equalsInt(1))
+ return ReplaceInstUsesWith(I, Op0);
+
+ // (X / C1) / C2 -> X / (C1*C2)
+ if (Instruction *LHS = dyn_cast<Instruction>(Op0))
+ if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
+ if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
+ return BinaryOperator::create(I.getOpcode(), LHS->getOperand(0),
+ ConstantExpr::getMul(RHS, LHSRHS));
}
+
+ if (!RHS->isNullValue()) { // avoid X udiv 0
+ 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;
+ }
}
// 0 / X == 0, we don't need to preserve faults!
@@ -2274,60 +2253,107 @@
Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- Instruction* common = commonDivTransforms(I);
- if (common)
- return common;
-
- common = commonIDivTransforms(I);
- if (common)
- return common;
+ // Handle the integer div common cases
+ if (Instruction *Common = commonIDivTransforms(I))
+ return Common;
+ // X udiv C^2 -> X >> C
// 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>(Op1)) {
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));
+ uint64_t ShiftAmt = Log2_64(Val);
+ Value* X = Op0;
+ const Type* XTy = X->getType();
+ bool isSigned = XTy->isSigned();
+ if (isSigned)
+ X = InsertNewInstBefore(
+ new CastInst(X, XTy->getUnsignedVersion(),"tmp"), I);
+ Instruction* Result =
+ new ShiftInst(Instruction::Shr, X,
+ ConstantInt::get(Type::UByteTy, ShiftAmt));
+ if (!isSigned)
+ return Result;
+ InsertNewInstBefore(Result, I);
+ return new CastInst(Result, XTy->getSignedVersion(), I.getName());
}
}
- if (Instruction *RHSI = dyn_cast<Instruction>(I.getOperand(1))) {
- // Turn A / (C1 << N), where C1 is "1<<C2" into A >> (N+C2) [udiv only].
+ // X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
+ if (ShiftInst *RHSI = dyn_cast<ShiftInst>(I.getOperand(1))) {
if (RHSI->getOpcode() == Instruction::Shl &&
- isa<ConstantInt>(RHSI->getOperand(0)) &&
- RHSI->getOperand(0)->getType()->isUnsigned()) {
+ isa<ConstantInt>(RHSI->getOperand(0))) {
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);
+ Value *N = RHSI->getOperand(1);
+ const Type* NTy = N->getType();
+ bool isSigned = NTy->isSigned();
+ if (uint64_t C2 = Log2_64(C1)) {
+ if (isSigned) {
+ NTy = NTy->getUnsignedVersion();
+ N = InsertNewInstBefore(new CastInst(N, NTy, "tmp"), I);
+ }
+ Constant *C2V = ConstantInt::get(NTy, C2);
+ N = InsertNewInstBefore(BinaryOperator::createAdd(N, C2V, "tmp"), I);
}
- return new ShiftInst(Instruction::Shr, Op0, Add);
+ Instruction* Result = new ShiftInst(Instruction::Shr, Op0, N);
+ if (!isSigned)
+ return Result;
+ InsertNewInstBefore(Result, I);
+ return new CastInst(Result, NTy->getSignedVersion(), I.getName());
}
}
}
+ // udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1), (shr X, C2)
+ // where C1&C2 are powers of two.
+ if (SelectInst *SI = dyn_cast<SelectInst>(Op1)) {
+ 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())
+ if (!STO->isNullValue() && !STO->isNullValue()) {
+ uint64_t TVA = STO->getZExtValue(), FVA = SFO->getZExtValue();
+ if (isPowerOf2_64(TVA) && isPowerOf2_64(FVA)) {
+ // Compute the shift amounts
+ unsigned TSA = Log2_64(TVA), FSA = Log2_64(FVA);
+ // Make sure we get the unsigned version of X
+ Value* X = Op0;
+ if (X->getType()->isSigned())
+ X = InsertNewInstBefore(
+ new CastInst(X, X->getType()->getUnsignedVersion()), I);
+ // Construct the "on true" case of the select
+ Constant *TC = ConstantInt::get(Type::UByteTy, TSA);
+ Instruction *TSI =
+ new ShiftInst(Instruction::Shr, X, TC, SI->getName()+".t");
+ TSI = InsertNewInstBefore(TSI, I);
+
+ // Construct the "on false" case of the select
+ Constant *FC = ConstantInt::get(Type::UByteTy, FSA);
+ Instruction *FSI =
+ new ShiftInst(Instruction::Shr, X, FC, SI->getName()+".f");
+ FSI = InsertNewInstBefore(FSI, I);
+
+ // Finally, construct the select instruction and return it.
+ return new SelectInst(SI->getOperand(0), TSI, FSI);
+ }
+ }
+ }
return 0;
}
Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- Instruction* common = commonDivTransforms(I);
- if (common)
- return common;
-
- common = commonIDivTransforms(I);
- if (common)
- return common;
+ // Handle the integer div common cases
+ if (Instruction *Common = commonIDivTransforms(I))
+ return Common;
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
+ // sdiv X, -1 == -X
+ if (RHS->isAllOnesValue())
+ return BinaryOperator::createNeg(Op0);
+
// -X/C -> X/-C
if (Value *LHSNeg = dyn_castNegVal(Op0))
return BinaryOperator::createSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
@@ -2337,17 +2363,7 @@
// 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 BinaryOperator::createUDiv(Op0, Op1, I.getName());
}
return 0;
@@ -2356,44 +2372,7 @@
Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- Instruction* common = commonDivTransforms(I);
- if (common)
- return common;
-
- // 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;
- }
- }
-
- return 0;
+ return commonDivTransforms(I);
}
/// GetFactor - If we can prove that the specified value is at least a multiple
@@ -3887,16 +3866,6 @@
return Changed ? &I : 0;
}
-/// MulWithOverflow - Compute Result = In1*In2, returning true if the result
-/// overflowed for this type.
-static bool MulWithOverflow(ConstantInt *&Result, ConstantInt *In1,
- ConstantInt *In2) {
- Result = cast<ConstantInt>(ConstantExpr::getMul(In1, In2));
- return !In2->isNullValue() && (In2->getType()->isSigned() ?
- ConstantExpr::getSDiv(Result, In2) :
- ConstantExpr::getUDiv(Result, In2)) != In1;
-}
-
static bool isPositive(ConstantInt *C) {
return C->getSExtValue() >= 0;
}
@@ -4298,7 +4267,9 @@
}
}
-
+ // Since the RHS is a constantInt (CI), if the left hand side is an
+ // instruction, see if that instruction also has constants so that the
+ // instruction can be folded into the setcc
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
switch (LHSI->getOpcode()) {
case Instruction::And:
@@ -4553,26 +4524,57 @@
case Instruction::SDiv:
case Instruction::UDiv:
- // Fold: (div X, C1) op C2 -> range check
+ // Fold: setcc ([us]div X, C1), C2 -> range test
+ // Fold this div into the comparison, producing a range check.
+ // Determine, based on the divide type, what the range is being
+ // checked. If there is an overflow on the low or high side, remember
+ // it, otherwise compute the range [low, hi) bounding the new value.
+ // See: InsertRangeTest above for the kinds of replacements possible.
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
- // Fold this div into the comparison, producing a range check.
- // Determine, based on the divide type, what the range is being
- // checked. If there is an overflow on the low or high side, remember
- // it, otherwise compute the range [low, hi) bounding the new value.
- bool LoOverflow = false, HiOverflow = 0;
+ // FIXME: If the operand types don't match the type of the divide
+ // then don't attempt this transform. The code below doesn't have the
+ // logic to deal with a signed divide and an unsigned compare (and
+ // vice versa). This is because (x /s C1) <s C2 produces different
+ // results than (x /s C1) <u C2 or (x /u C1) <s C2 or even
+ // (x /u C1) <u C2. Simply casting the operands and result won't
+ // work. :( The if statement below tests that condition and bails
+ // if it finds it.
+ const Type* DivRHSTy = DivRHS->getType();
+ unsigned DivOpCode = LHSI->getOpcode();
+ if ((DivOpCode == Instruction::SDiv && DivRHSTy->isUnsigned()) ||
+ (DivOpCode == Instruction::UDiv && DivRHSTy->isSigned()))
+ break;
+
+ // Initialize the variables that will indicate the nature of the
+ // range check.
+ bool LoOverflow = false, HiOverflow = false;
ConstantInt *LoBound = 0, *HiBound = 0;
- ConstantInt *Prod;
- bool ProdOV = MulWithOverflow(Prod, CI, DivRHS);
+ // Compute Prod = CI * DivRHS. We are essentially solving an equation
+ // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and
+ // C2 (CI). By solving for X we can turn this into a range check
+ // instead of computing a divide.
+ ConstantInt *Prod =
+ cast<ConstantInt>(ConstantExpr::getMul(CI, DivRHS));
+
+ // Determine if the product overflows by seeing if the product is
+ // not equal to the divide. Make sure we do the same kind of divide
+ // as in the LHS instruction that we're folding.
+ bool ProdOV = !DivRHS->isNullValue() &&
+ (DivOpCode == Instruction::SDiv ?
+ ConstantExpr::getSDiv(Prod, DivRHS) :
+ ConstantExpr::getUDiv(Prod, DivRHS)) != CI;
+ // Get the SetCC opcode
Instruction::BinaryOps Opcode = I.getOpcode();
- if (DivRHS->isNullValue()) { // Don't hack on divide by zeros.
- } else if (LHSI->getType()->isUnsigned()) { // udiv
+ if (DivRHS->isNullValue()) {
+ // Don't hack on divide by zeros!
+ } else if (DivOpCode == Instruction::UDiv) { // udiv
LoBound = Prod;
LoOverflow = ProdOV;
HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS);
- } else if (isPositive(DivRHS)) { // Divisor is > 0.
+ } else if (isPositive(DivRHS)) { // Divisor is > 0.
if (CI->isNullValue()) { // (X / pos) op 0
// Can't overflow.
LoBound = cast<ConstantInt>(ConstantExpr::getNeg(SubOne(DivRHS)));
@@ -4588,12 +4590,12 @@
HiBound = Prod;
HiOverflow = ProdOV;
}
- } else { // Divisor is < 0.
+ } else { // Divisor is < 0.
if (CI->isNullValue()) { // (X / neg) op 0
LoBound = AddOne(DivRHS);
HiBound = cast<ConstantInt>(ConstantExpr::getNeg(DivRHS));
if (HiBound == DivRHS)
- LoBound = 0; // - INTMIN = INTMIN
+ LoBound = 0; // - INTMIN = INTMIN
} else if (isPositive(CI)) { // (X / neg) op pos
HiOverflow = LoOverflow = ProdOV;
if (!LoOverflow)
@@ -5790,7 +5792,8 @@
unsigned SrcBitSize = Src->getType()->getPrimitiveSizeInBits();
unsigned DestBitSize = CI.getType()->getPrimitiveSizeInBits();
assert(SrcBitSize < DestBitSize && "Not a zext?");
- Constant *C = ConstantInt::get(Type::ULongTy, (1 << SrcBitSize)-1);
+ Constant *C =
+ ConstantInt::get(Type::ULongTy, (1ULL << SrcBitSize)-1);
C = ConstantExpr::getCast(C, CI.getType());
return BinaryOperator::createAnd(Res, C);
}
@@ -5838,6 +5841,23 @@
ConstantInt::get(CI.getType(), 1));
}
break;
+ case Instruction::SDiv:
+ case Instruction::UDiv:
+ // If we are just changing the sign, rewrite.
+ if (DestBitSize == SrcBitSize) {
+ // Don't insert two casts if they cannot be eliminated. We allow two
+ // casts to be inserted if the sizes are the same. This could only be
+ // converting signedness, which is a noop.
+ if (!ValueRequiresCast(Op1, DestTy,TD) ||
+ !ValueRequiresCast(Op0, DestTy, TD)) {
+ Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
+ Value *Op1c = InsertOperandCastBefore(Op1, DestTy, SrcI);
+ return BinaryOperator::create(
+ cast<BinaryOperator>(SrcI)->getOpcode(), Op0c, Op1c);
+ }
+ }
+ break;
+
case Instruction::Shl:
// Allow changing the sign of the source operand. Do not allow changing
// the size of the shift, UNLESS the shift amount is a constant. We
More information about the llvm-commits
mailing list