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. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits