From a96879a26dad2e68af65fc985e89b4e8773ea726 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 29 Sep 2004 17:40:11 +0000 Subject: [PATCH] * Pull range optimization code out into new InsertRangeTest function. * SubOne/AddOne functions always return ConstantInt, declare them as such * Pull code for handling setcc X, cst, where cst is at the end of the range, or cc is LE or GE up earlier in visitSetCondInst. This reduces #iterations in some cases. * Fold: (div X, C1) op C2 -> range check, implementing div.ll:test6 - test9. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16588 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 299 +++++++++++++----- 1 file changed, 219 insertions(+), 80 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 1cd2c4657ee..ec50320056d 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -209,6 +209,9 @@ namespace { Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS, ConstantIntegral *AndRHS, BinaryOperator &TheAnd); + + Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, + bool Inside, Instruction &IB); }; RegisterOpt X("instcombine", "Combine redundant instructions"); @@ -341,11 +344,13 @@ static unsigned Log2(uint64_t Val) { } // AddOne, SubOne - Add or subtract a constant one from an integer constant... -static Constant *AddOne(ConstantInt *C) { - return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1)); +static ConstantInt *AddOne(ConstantInt *C) { + return cast(ConstantExpr::getAdd(C, + ConstantInt::get(C->getType(), 1))); } -static Constant *SubOne(ConstantInt *C) { - return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1)); +static ConstantInt *SubOne(ConstantInt *C) { + return cast(ConstantExpr::getSub(C, + ConstantInt::get(C->getType(), 1))); } // isTrueWhenEqual - Return true if the specified setcondinst instruction is @@ -1241,6 +1246,51 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op, } +/// InsertRangeTest - Emit a computation of: (V >= Lo && V < Hi) if Inside is +/// true, otherwise (V < Lo || V >= Hi). In pratice, we emit the more efficient +/// (V-Lo) (ConstantExpr::getSetLE(Lo, Hi))->getValue() && + "Lo is not <= Hi in range emission code!"); + if (Inside) { + if (Lo == Hi) // Trivially false. + return new SetCondInst(Instruction::SetNE, V, V); + if (cast(Lo)->isMinValue()) + return new SetCondInst(Instruction::SetLT, V, Hi); + + Constant *AddCST = ConstantExpr::getNeg(Lo); + Instruction *Add = BinaryOperator::createAdd(V, AddCST,V->getName()+".off"); + InsertNewInstBefore(Add, IB); + // Convert to unsigned for the comparison. + const Type *UnsType = Add->getType()->getUnsignedVersion(); + Value *OffsetVal = InsertCastBefore(Add, UnsType, IB); + AddCST = ConstantExpr::getAdd(AddCST, Hi); + AddCST = ConstantExpr::getCast(AddCST, UnsType); + return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST); + } + + if (Lo == Hi) // Trivially true. + return new SetCondInst(Instruction::SetEQ, V, V); + + Hi = SubOne(cast(Hi)); + if (cast(Lo)->isMinValue()) // V < 0 || V >= Hi ->'V > Hi-1' + return new SetCondInst(Instruction::SetGT, V, Hi); + + // Emit X-Lo > Hi-Lo-1 + Constant *AddCST = ConstantExpr::getNeg(Lo); + Instruction *Add = BinaryOperator::createAdd(V, AddCST, V->getName()+".off"); + InsertNewInstBefore(Add, IB); + // Convert to unsigned for the comparison. + const Type *UnsType = Add->getType()->getUnsignedVersion(); + Value *OffsetVal = InsertCastBefore(Add, UnsType, IB); + AddCST = ConstantExpr::getAdd(AddCST, Hi); + AddCST = ConstantExpr::getCast(AddCST, UnsType); + return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST); +} + + Instruction *InstCombiner::visitAnd(BinaryOperator &I) { bool Changed = SimplifyCommutative(I); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -1375,19 +1425,8 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { if (RHSCst == AddOne(LHSCst)) // (X > 13 & X != 14) -> X > 14 return new SetCondInst(Instruction::SetGT, LHSVal, RHSCst); break; // (X > 13 & X != 15) -> no change - case Instruction::SetLT: { // (X > 13 & X < 15) -> (X-14) getName()+".off"); - InsertNewInstBefore(Add, I); - // Convert to unsigned for the comparison. - const Type *UnsType = Add->getType()->getUnsignedVersion(); - Value *OffsetVal = InsertCastBefore(Add, UnsType, I); - AddCST = ConstantExpr::getAdd(AddCST, RHSCst); - AddCST = ConstantExpr::getCast(AddCST, UnsType); - return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST); - } - break; + case Instruction::SetLT: // (X > 13 & X < 15) -> (X-14) no change break; - case Instruction::SetGT: {// (X < 13 | X > 15) -> (X-13) > 2 - Constant *AddCST = ConstantExpr::getNeg(LHSCst); - Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST, - LHSVal->getName()+".off"); - InsertNewInstBefore(Add, I); - // Convert to unsigned for the comparison. - const Type *UnsType = Add->getType()->getUnsignedVersion(); - Value *OffsetVal = InsertCastBefore(Add, UnsType, I); - AddCST = ConstantExpr::getAdd(AddCST, RHSCst); - AddCST = ConstantExpr::getCast(AddCST, UnsType); - return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST); - } + case Instruction::SetGT: // (X < 13 | X > 15) -> (X-13) > 2 + return InsertRangeTest(LHSVal, LHSCst, AddOne(RHSCst), false, I); case Instruction::SetNE: // (X < 13 | X != 15) -> X != 15 case Instruction::SetLT: // (X < 13 | X < 15) -> X < 15 return ReplaceInstUsesWith(I, RHS); @@ -1721,6 +1748,36 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { 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(ConstantExpr::getMul(In1, In2)); + return !In2->isNullValue() && ConstantExpr::getDiv(Result, In2) != In1; +} + +static bool isPositive(ConstantInt *C) { + return cast(C)->getValue() >= 0; +} + +/// AddWithOverflow - Compute Result = In1+In2, returning true if the result +/// overflowed for this type. +static bool AddWithOverflow(ConstantInt *&Result, ConstantInt *In1, + ConstantInt *In2) { + Result = cast(ConstantExpr::getAdd(In1, In2)); + + if (In1->getType()->isUnsigned()) + return cast(Result)->getValue() < + cast(In1)->getValue(); + if (isPositive(In1) != isPositive(In2)) + return false; + if (isPositive(In1)) + return cast(Result)->getValue() < + cast(In1)->getValue(); + return cast(Result)->getValue() > + cast(In1)->getValue(); +} + Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { bool Changed = SimplifyCommutative(I); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -1770,6 +1827,50 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { // See if we are doing a comparison between a constant and an instruction that // can be folded into the comparison. if (ConstantInt *CI = dyn_cast(Op1)) { + // Check to see if we are comparing against the minimum or maximum value... + if (CI->isMinValue()) { + if (I.getOpcode() == Instruction::SetLT) // A < MIN -> FALSE + return ReplaceInstUsesWith(I, ConstantBool::False); + if (I.getOpcode() == Instruction::SetGE) // A >= MIN -> TRUE + return ReplaceInstUsesWith(I, ConstantBool::True); + if (I.getOpcode() == Instruction::SetLE) // A <= MIN -> A == MIN + return BinaryOperator::createSetEQ(Op0, Op1); + if (I.getOpcode() == Instruction::SetGT) // A > MIN -> A != MIN + return BinaryOperator::createSetNE(Op0, Op1); + + } else if (CI->isMaxValue()) { + if (I.getOpcode() == Instruction::SetGT) // A > MAX -> FALSE + return ReplaceInstUsesWith(I, ConstantBool::False); + if (I.getOpcode() == Instruction::SetLE) // A <= MAX -> TRUE + return ReplaceInstUsesWith(I, ConstantBool::True); + if (I.getOpcode() == Instruction::SetGE) // A >= MAX -> A == MAX + return BinaryOperator::createSetEQ(Op0, Op1); + if (I.getOpcode() == Instruction::SetLT) // A < MAX -> A != MAX + return BinaryOperator::createSetNE(Op0, Op1); + + // Comparing against a value really close to min or max? + } else if (isMinValuePlusOne(CI)) { + if (I.getOpcode() == Instruction::SetLT) // A < MIN+1 -> A == MIN + return BinaryOperator::createSetEQ(Op0, SubOne(CI)); + if (I.getOpcode() == Instruction::SetGE) // A >= MIN-1 -> A != MIN + return BinaryOperator::createSetNE(Op0, SubOne(CI)); + + } else if (isMaxValueMinusOne(CI)) { + if (I.getOpcode() == Instruction::SetGT) // A > MAX-1 -> A == MAX + return BinaryOperator::createSetEQ(Op0, AddOne(CI)); + if (I.getOpcode() == Instruction::SetLE) // A <= MAX-1 -> A != MAX + return BinaryOperator::createSetNE(Op0, AddOne(CI)); + } + + // If we still have a setle or setge instruction, turn it into the + // appropriate setlt or setgt instruction. Since the border cases have + // already been handled above, this requires little checking. + // + if (I.getOpcode() == Instruction::SetLE) + return BinaryOperator::createSetLT(Op0, AddOne(CI)); + if (I.getOpcode() == Instruction::SetGE) + return BinaryOperator::createSetGT(Op0, SubOne(CI)); + if (Instruction *LHSI = dyn_cast(Op0)) switch (LHSI->getOpcode()) { case Instruction::PHI: @@ -1864,12 +1965,8 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { return ReplaceInstUsesWith(I, ConstantBool::True); case Instruction::SetLT: return ReplaceInstUsesWith(I, ConstantExpr::getSetLT(Max, CI)); - case Instruction::SetLE: - return ReplaceInstUsesWith(I, ConstantExpr::getSetLE(Max, CI)); case Instruction::SetGT: return ReplaceInstUsesWith(I, ConstantExpr::getSetGT(Min, CI)); - case Instruction::SetGE: - return ReplaceInstUsesWith(I, ConstantExpr::getSetGE(Min, CI)); } } @@ -1968,6 +2065,92 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { } break; + case Instruction::Div: + // Fold: (div X, C1) op C2 -> range check + if (ConstantInt *DivRHS = dyn_cast(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; + ConstantInt *LoBound = 0, *HiBound = 0; + + ConstantInt *Prod; + bool ProdOV = MulWithOverflow(Prod, CI, DivRHS); + + if (DivRHS->isNullValue()) { // Don't hack on divide by zeros. + } else if (LHSI->getType()->isUnsigned()) { // udiv + LoBound = Prod; + LoOverflow = ProdOV; + HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS); + } else if (isPositive(DivRHS)) { // Divisor is > 0. + if (CI->isNullValue()) { // (X / pos) op 0 + // Can't overflow. + LoBound = cast(ConstantExpr::getNeg(SubOne(DivRHS))); + HiBound = DivRHS; + } else if (isPositive(CI)) { // (X / pos) op pos + LoBound = Prod; + LoOverflow = ProdOV; + HiOverflow = ProdOV || AddWithOverflow(HiBound, Prod, DivRHS); + } else { // (X / pos) op neg + Constant *DivRHSH = ConstantExpr::getNeg(SubOne(DivRHS)); + LoOverflow = AddWithOverflow(LoBound, Prod, + cast(DivRHSH)); + HiBound = Prod; + HiOverflow = ProdOV; + } + } else { // Divisor is < 0. + if (CI->isNullValue()) { // (X / neg) op 0 + LoBound = AddOne(DivRHS); + HiBound = cast(ConstantExpr::getNeg(DivRHS)); + } else if (isPositive(CI)) { // (X / neg) op pos + HiOverflow = LoOverflow = ProdOV; + if (!LoOverflow) + LoOverflow = AddWithOverflow(LoBound, Prod, AddOne(DivRHS)); + HiBound = AddOne(Prod); + } else { // (X / neg) op neg + LoBound = Prod; + LoOverflow = HiOverflow = ProdOV; + HiBound = cast(ConstantExpr::getSub(Prod, DivRHS)); + } + } + + if (LoBound) { + Value *X = LHSI->getOperand(0); + std::cerr << "DIV FOLD: " << *LHSI; + std::cerr << "DIV FOLD: " << I << "\n"; + switch (I.getOpcode()) { + default: assert(0 && "Unhandled setcc opcode!"); + case Instruction::SetEQ: + if (LoOverflow && HiOverflow) + return ReplaceInstUsesWith(I, ConstantBool::False); + else if (HiOverflow) + return new SetCondInst(Instruction::SetGE, X, LoBound); + else if (LoOverflow) + return new SetCondInst(Instruction::SetLT, X, HiBound); + else + return InsertRangeTest(X, LoBound, HiBound, true, I); + case Instruction::SetNE: + if (LoOverflow && HiOverflow) + return ReplaceInstUsesWith(I, ConstantBool::True); + else if (HiOverflow) + return new SetCondInst(Instruction::SetLT, X, LoBound); + else if (LoOverflow) + return new SetCondInst(Instruction::SetGE, X, HiBound); + else + return InsertRangeTest(X, LoBound, HiBound, false, I); + case Instruction::SetLT: + if (LoOverflow) + return ReplaceInstUsesWith(I, ConstantBool::False); + return new SetCondInst(Instruction::SetLT, X, LoBound); + case Instruction::SetGT: + if (HiOverflow) + return ReplaceInstUsesWith(I, ConstantBool::False); + return new SetCondInst(Instruction::SetGE, X, HiBound); + } + } + } + break; case Instruction::Select: // If either operand of the select is a constant, we can fold the // comparison into the select arms, which will cause one to be @@ -2157,50 +2340,6 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { } } } - - // Check to see if we are comparing against the minimum or maximum value... - if (CI->isMinValue()) { - if (I.getOpcode() == Instruction::SetLT) // A < MIN -> FALSE - return ReplaceInstUsesWith(I, ConstantBool::False); - if (I.getOpcode() == Instruction::SetGE) // A >= MIN -> TRUE - return ReplaceInstUsesWith(I, ConstantBool::True); - if (I.getOpcode() == Instruction::SetLE) // A <= MIN -> A == MIN - return BinaryOperator::createSetEQ(Op0, Op1); - if (I.getOpcode() == Instruction::SetGT) // A > MIN -> A != MIN - return BinaryOperator::createSetNE(Op0, Op1); - - } else if (CI->isMaxValue()) { - if (I.getOpcode() == Instruction::SetGT) // A > MAX -> FALSE - return ReplaceInstUsesWith(I, ConstantBool::False); - if (I.getOpcode() == Instruction::SetLE) // A <= MAX -> TRUE - return ReplaceInstUsesWith(I, ConstantBool::True); - if (I.getOpcode() == Instruction::SetGE) // A >= MAX -> A == MAX - return BinaryOperator::createSetEQ(Op0, Op1); - if (I.getOpcode() == Instruction::SetLT) // A < MAX -> A != MAX - return BinaryOperator::createSetNE(Op0, Op1); - - // Comparing against a value really close to min or max? - } else if (isMinValuePlusOne(CI)) { - if (I.getOpcode() == Instruction::SetLT) // A < MIN+1 -> A == MIN - return BinaryOperator::createSetEQ(Op0, SubOne(CI)); - if (I.getOpcode() == Instruction::SetGE) // A >= MIN-1 -> A != MIN - return BinaryOperator::createSetNE(Op0, SubOne(CI)); - - } else if (isMaxValueMinusOne(CI)) { - if (I.getOpcode() == Instruction::SetGT) // A > MAX-1 -> A == MAX - return BinaryOperator::createSetEQ(Op0, AddOne(CI)); - if (I.getOpcode() == Instruction::SetLE) // A <= MAX-1 -> A != MAX - return BinaryOperator::createSetNE(Op0, AddOne(CI)); - } - - // If we still have a setle or setge instruction, turn it into the - // appropriate setlt or setgt instruction. Since the border cases have - // already been handled above, this requires little checking. - // - if (I.getOpcode() == Instruction::SetLE) - return BinaryOperator::createSetLT(Op0, AddOne(CI)); - if (I.getOpcode() == Instruction::SetGE) - return BinaryOperator::createSetGT(Op0, SubOne(CI)); } // Test to see if the operands of the setcc are casted versions of other @@ -2875,7 +3014,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { } } } - + if (Instruction *FVI = dyn_cast(FalseVal)) if (FVI->hasOneUse() && FVI->getNumOperands() == 2 && !isa(TrueVal))