X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FScalar%2FInstructionCombining.cpp;h=92b7f1a39bc719a7c367ff8fadc1463d8f10dc2e;hb=6ffe551f657c948d6a473a198ecbd1188bf9ce45;hp=03477e0887fe0db7782cf25778056cde11b9c596;hpb=cb69a4ed6424af04ea9c4705ce3674483dc4e02a;p=oota-llvm.git diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 03477e0887f..92b7f1a39bc 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -397,30 +397,6 @@ Instruction *AssociativeOpt(BinaryOperator &Root, const Functor &F) { // reassociate the expression from ((? op A) op B) to (? op (A op B)) if (ShouldApply) { BasicBlock *BB = Root.getParent(); - // All of the instructions have a single use and have no side-effects, - // because of this, we can pull them all into the current basic block. - if (LHSI->getParent() != BB) { - // Move all of the instructions from root to LHSI into the current - // block. - Instruction *TmpLHSI = cast(Root.getOperand(0)); - Instruction *LastUse = &Root; - while (TmpLHSI->getParent() == BB) { - LastUse = TmpLHSI; - TmpLHSI = cast(TmpLHSI->getOperand(0)); - } - - // Loop over all of the instructions in other blocks, moving them into - // the current one. - Value *TmpLHS = TmpLHSI; - do { - TmpLHSI = cast(TmpLHS); - // Remove from current block... - TmpLHSI->getParent()->getInstList().remove(TmpLHSI); - // Insert before the last instruction... - BB->getInstList().insert(LastUse, TmpLHSI); - TmpLHS = TmpLHSI->getOperand(0); - } while (TmpLHSI != LHSI); - } // Now all of the instructions are in the current basic block, go ahead // and perform the reassociation. @@ -431,20 +407,27 @@ Instruction *AssociativeOpt(BinaryOperator &Root, const Functor &F) { // Make what used to be the LHS of the root be the user of the root... Value *ExtraOperand = TmpLHSI->getOperand(1); - if (&Root != TmpLHSI) - Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI - else { + if (&Root == TmpLHSI) { Root.replaceAllUsesWith(Constant::getNullValue(TmpLHSI->getType())); return 0; } + Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI TmpLHSI->setOperand(1, &Root); // TmpLHSI now uses the root - BB->getInstList().remove(&Root); // Remove root from the BB - BB->getInstList().insert(TmpLHSI, &Root); // Insert root before TmpLHSI + TmpLHSI->getParent()->getInstList().remove(TmpLHSI); + BasicBlock::iterator ARI = &Root; ++ARI; + BB->getInstList().insert(ARI, TmpLHSI); // Move TmpLHSI to after Root + ARI = Root; // Now propagate the ExtraOperand down the chain of instructions until we // get to LHSI. while (TmpLHSI != LHSI) { Instruction *NextLHSI = cast(TmpLHSI->getOperand(0)); + // Move the instruction to immediately before the chain we are + // constructing to avoid breaking dominance properties. + NextLHSI->getParent()->getInstList().remove(NextLHSI); + BB->getInstList().insert(ARI, NextLHSI); + ARI = NextLHSI; + Value *NextOp = NextLHSI->getOperand(1); NextLHSI->setOperand(1, ExtraOperand); TmpLHSI = NextLHSI; @@ -489,16 +472,71 @@ struct AddMaskingAnd { } }; +static Value *FoldOperationIntoSelectOperand(Instruction &BI, Value *SO, + InstCombiner *IC) { + // Figure out if the constant is the left or the right argument. + bool ConstIsRHS = isa(BI.getOperand(1)); + Constant *ConstOperand = cast(BI.getOperand(ConstIsRHS)); + if (Constant *SOC = dyn_cast(SO)) { + if (ConstIsRHS) + return ConstantExpr::get(BI.getOpcode(), SOC, ConstOperand); + return ConstantExpr::get(BI.getOpcode(), ConstOperand, SOC); + } + + Value *Op0 = SO, *Op1 = ConstOperand; + if (!ConstIsRHS) + std::swap(Op0, Op1); + Instruction *New; + if (BinaryOperator *BO = dyn_cast(&BI)) + New = BinaryOperator::create(BO->getOpcode(), Op0, Op1); + else if (ShiftInst *SI = dyn_cast(&BI)) + New = new ShiftInst(SI->getOpcode(), Op0, Op1); + else { + assert(0 && "Unknown binary instruction type!"); + abort(); + } + return IC->InsertNewInstBefore(New, BI); +} + +// FoldBinOpIntoSelect - Given an instruction with a select as one operand and a +// constant as the other operand, try to fold the binary operator into the +// select arguments. +static Instruction *FoldBinOpIntoSelect(Instruction &BI, SelectInst *SI, + InstCombiner *IC) { + // Don't modify shared select instructions + if (!SI->hasOneUse()) return 0; + Value *TV = SI->getOperand(1); + Value *FV = SI->getOperand(2); + + if (isa(TV) || isa(FV)) { + Value *SelectTrueVal = FoldOperationIntoSelectOperand(BI, TV, IC); + Value *SelectFalseVal = FoldOperationIntoSelectOperand(BI, FV, IC); + + return new SelectInst(SI->getCondition(), SelectTrueVal, + SelectFalseVal); + } + return 0; +} Instruction *InstCombiner::visitAdd(BinaryOperator &I) { bool Changed = SimplifyCommutative(I); Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); - // X + 0 --> X - if (!I.getType()->isFloatingPoint() && // -0 + +0 = +0, so it's not a noop - RHS == Constant::getNullValue(I.getType())) - return ReplaceInstUsesWith(I, LHS); + if (Constant *RHSC = dyn_cast(RHS)) { + // X + 0 --> X + if (!I.getType()->isFloatingPoint() && // -0 + +0 = +0, so it's not a noop + RHSC->isNullValue()) + return ReplaceInstUsesWith(I, LHS); + + // X + (signbit) --> X ^ signbit + if (ConstantInt *CI = dyn_cast(RHSC)) { + unsigned NumBits = CI->getType()->getPrimitiveSize()*8; + uint64_t Val = CI->getRawValue() & (1ULL << NumBits)-1; + if (Val == (1ULL << NumBits-1)) + return BinaryOperator::create(Instruction::Xor, LHS, RHS); + } + } // X + X --> X << 1 if (I.getType()->isInteger()) @@ -547,6 +585,11 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { CRHS, ConstantInt::get(I.getType(), 1)), ILHS->getOperand(0)); break; + case Instruction::Select: + // Try to fold constant add into select arguments. + if (Instruction *R = FoldBinOpIntoSelect(I,cast(ILHS),this)) + return R; + default: break; } } @@ -632,6 +675,11 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { } } } + + // Try to fold constant sub into select arguments. + if (SelectInst *SI = dyn_cast(Op1)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; } if (BinaryOperator *Op1I = dyn_cast(Op1)) @@ -740,6 +788,11 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { if (Op1F->getValue() == 1.0) return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0' } + + // Try to fold constant mul into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; } if (Value *Op0v = dyn_castNegVal(Op0)) // -X * -Y = X*Y @@ -796,11 +849,15 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { } Instruction *InstCombiner::visitDiv(BinaryOperator &I) { - // div X, 1 == X if (ConstantInt *RHS = dyn_cast(I.getOperand(1))) { + // div X, 1 == X if (RHS->equalsInt(1)) return ReplaceInstUsesWith(I, I.getOperand(0)); + // div X, -1 == -X + if (RHS->isAllOnesValue()) + return BinaryOperator::createNeg(I.getOperand(0)); + // Check to see if this is an unsigned division with an exact power of 2, // if so, convert to a right shift. if (ConstantUInt *C = dyn_cast(RHS)) @@ -1093,6 +1150,11 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { if (Instruction *Res = OptAndOp(Op0I, Op0CI, RHS, I)) return Res; } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; } Value *Op0NotVal = dyn_castNotVal(Op0); @@ -1158,6 +1220,11 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { NotConstant(RHS))); } } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; } // (A & C1)|(A & C2) == A & (C1|C2) @@ -1268,6 +1335,11 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { default: break; } } + + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; } if (Value *X = dyn_castNotVal(Op0)) // ~A ^ A == -1 @@ -1668,6 +1740,12 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { if (CSI->isAllOnesValue()) return ReplaceInstUsesWith(I, CSI); + // Try to fold constant and into select arguments. + if (isa(Op0)) + if (SelectInst *SI = dyn_cast(Op1)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; + if (ConstantUInt *CUI = dyn_cast(Op1)) { // shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr // of a signed value. @@ -1689,6 +1767,10 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { return BinaryOperator::create(Instruction::Mul, BO->getOperand(0), ConstantExpr::get(Instruction::Shl, BOOp, CUI)); + // Try to fold constant and into select arguments. + if (SelectInst *SI = dyn_cast(Op0)) + if (Instruction *R = FoldBinOpIntoSelect(I, SI, this)) + return R; // If the operand is an bitwise operator with a constant RHS, and the // shift is the only use, we can pull it out of the shift. @@ -2008,6 +2090,54 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) { return 0; } +/// GetSelectFoldableOperands - We want to turn code that looks like this: +/// %C = or %A, %B +/// %D = select %cond, %C, %A +/// into: +/// %C = select %cond, %B, 0 +/// %D = or %A, %C +/// +/// Assuming that the specified instruction is an operand to the select, return +/// a bitmask indicating which operands of this instruction are foldable if they +/// equal the other incoming value of the select. +/// +static unsigned GetSelectFoldableOperands(Instruction *I) { + switch (I->getOpcode()) { + case Instruction::Add: + case Instruction::Mul: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + return 3; // Can fold through either operand. + case Instruction::Sub: // Can only fold on the amount subtracted. + case Instruction::Shl: // Can only fold on the shift amount. + case Instruction::Shr: + return 1; + default: + return 0; // Cannot fold + } +} + +/// GetSelectFoldableConstant - For the same transformation as the previous +/// function, return the identity constant that goes into the select. +static Constant *GetSelectFoldableConstant(Instruction *I) { + switch (I->getOpcode()) { + default: assert(0 && "This cannot happen!"); abort(); + case Instruction::Add: + case Instruction::Sub: + case Instruction::Or: + case Instruction::Xor: + return Constant::getNullValue(I->getType()); + case Instruction::Shl: + case Instruction::Shr: + return Constant::getNullValue(Type::UByteTy); + case Instruction::And: + return ConstantInt::getAllOnesValue(I->getType()); + case Instruction::Mul: + return ConstantInt::get(I->getType(), 1); + } +} + Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { Value *CondVal = SI.getCondition(); Value *TrueVal = SI.getTrueValue(); @@ -2027,25 +2157,128 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { if (TrueVal == FalseVal) return ReplaceInstUsesWith(SI, TrueVal); - // Selecting between two constants? - if (Constant *TrueValC = dyn_cast(TrueVal)) - if (Constant *FalseValC = dyn_cast(FalseVal)) { - if (SI.getType() == Type::BoolTy && - isa(TrueValC) && isa(FalseValC)) { - // select C, true, false -> C - if (TrueValC == ConstantBool::True) - return ReplaceInstUsesWith(SI, CondVal); - // select C, false, true -> !C - return BinaryOperator::createNot(CondVal); + if (SI.getType() == Type::BoolTy) + if (ConstantBool *C = dyn_cast(TrueVal)) { + if (C == ConstantBool::True) { + // Change: A = select B, true, C --> A = or B, C + return BinaryOperator::create(Instruction::Or, CondVal, FalseVal); + } else { + // Change: A = select B, false, C --> A = and !B, C + Value *NotCond = + InsertNewInstBefore(BinaryOperator::createNot(CondVal, + "not."+CondVal->getName()), SI); + return BinaryOperator::create(Instruction::And, NotCond, FalseVal); } - - // If the true constant is a 1 and the false is a zero, turn this into a - // cast from bool. - if (FalseValC->isNullValue() && isa(TrueValC) && - cast(TrueValC)->getRawValue() == 1) + } else if (ConstantBool *C = dyn_cast(FalseVal)) { + if (C == ConstantBool::False) { + // Change: A = select B, C, false --> A = and B, C + return BinaryOperator::create(Instruction::And, CondVal, TrueVal); + } else { + // Change: A = select B, C, true --> A = or !B, C + Value *NotCond = + InsertNewInstBefore(BinaryOperator::createNot(CondVal, + "not."+CondVal->getName()), SI); + return BinaryOperator::create(Instruction::Or, NotCond, TrueVal); + } + } + + // Selecting between two integer constants? + if (ConstantInt *TrueValC = dyn_cast(TrueVal)) + if (ConstantInt *FalseValC = dyn_cast(FalseVal)) { + // select C, 1, 0 -> cast C to int + if (FalseValC->isNullValue() && TrueValC->getRawValue() == 1) { return new CastInst(CondVal, SI.getType()); + } else if (TrueValC->isNullValue() && FalseValC->getRawValue() == 1) { + // select C, 0, 1 -> cast !C to int + Value *NotCond = + InsertNewInstBefore(BinaryOperator::createNot(CondVal, + "not."+CondVal->getName()), SI); + return new CastInst(NotCond, SI.getType()); + } + } + + // See if we are selecting two values based on a comparison of the two values. + if (SetCondInst *SCI = dyn_cast(CondVal)) { + if (SCI->getOperand(0) == TrueVal && SCI->getOperand(1) == FalseVal) { + // Transform (X == Y) ? X : Y -> Y + if (SCI->getOpcode() == Instruction::SetEQ) + return ReplaceInstUsesWith(SI, FalseVal); + // Transform (X != Y) ? X : Y -> X + if (SCI->getOpcode() == Instruction::SetNE) + return ReplaceInstUsesWith(SI, TrueVal); + // NOTE: if we wanted to, this is where to detect MIN/MAX/ABS/etc. + + } else if (SCI->getOperand(0) == FalseVal && SCI->getOperand(1) == TrueVal){ + // Transform (X == Y) ? Y : X -> X + if (SCI->getOpcode() == Instruction::SetEQ) + return ReplaceInstUsesWith(SI, FalseVal); + // Transform (X != Y) ? Y : X -> Y + if (SCI->getOpcode() == Instruction::SetNE) + return ReplaceInstUsesWith(SI, TrueVal); + // NOTE: if we wanted to, this is where to detect MIN/MAX/ABS/etc. } + } + + // See if we can fold the select into one of our operands. + if (SI.getType()->isInteger()) { + // See the comment above GetSelectFoldableOperands for a description of the + // transformation we are doing here. + if (Instruction *TVI = dyn_cast(TrueVal)) + if (TVI->hasOneUse() && TVI->getNumOperands() == 2 && + !isa(FalseVal)) + if (unsigned SFO = GetSelectFoldableOperands(TVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && FalseVal == TVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { + OpToFold = 2; + } + + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(TVI); + std::string Name = TVI->getName(); TVI->setName(""); + Instruction *NewSel = + new SelectInst(SI.getCondition(), TVI->getOperand(2-OpToFold), C, + Name); + InsertNewInstBefore(NewSel, SI); + if (BinaryOperator *BO = dyn_cast(TVI)) + return BinaryOperator::create(BO->getOpcode(), FalseVal, NewSel); + else if (ShiftInst *SI = dyn_cast(TVI)) + return new ShiftInst(SI->getOpcode(), FalseVal, NewSel); + else { + assert(0 && "Unknown instruction!!"); + } + } + } + + if (Instruction *FVI = dyn_cast(FalseVal)) + if (FVI->hasOneUse() && FVI->getNumOperands() == 2 && + !isa(TrueVal)) + if (unsigned SFO = GetSelectFoldableOperands(FVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && TrueVal == FVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { + OpToFold = 2; + } + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(FVI); + std::string Name = FVI->getName(); FVI->setName(""); + Instruction *NewSel = + new SelectInst(SI.getCondition(), C, FVI->getOperand(2-OpToFold), + Name); + InsertNewInstBefore(NewSel, SI); + if (BinaryOperator *BO = dyn_cast(FVI)) + return BinaryOperator::create(BO->getOpcode(), TrueVal, NewSel); + else if (ShiftInst *SI = dyn_cast(FVI)) + return new ShiftInst(SI->getOpcode(), TrueVal, NewSel); + else { + assert(0 && "Unknown instruction!!"); + } + } + } + } return 0; } @@ -2177,9 +2410,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if ((*AI)->getType() == ParamTy) { Args.push_back(*AI); } else { - Instruction *Cast = new CastInst(*AI, ParamTy, "tmp"); - InsertNewInstBefore(Cast, *Caller); - Args.push_back(Cast); + Args.push_back(InsertNewInstBefore(new CastInst(*AI, ParamTy, "tmp"), + *Caller)); } } @@ -2352,7 +2584,10 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // obvious. Value *Op = GEP.getOperand(i); if (Op->getType()->getPrimitiveSize() > TD->getPointerSize()) - if (!isa(Op)) { + if (Constant *C = dyn_cast(Op)) { + GEP.setOperand(i, ConstantExpr::getCast(C, TD->getIntPtrType())); + MadeChange = true; + } else { Op = InsertNewInstBefore(new CastInst(Op, TD->getIntPtrType(), Op->getName()), GEP); GEP.setOperand(i, Op); @@ -2608,8 +2843,11 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { Value *Op = LI.getOperand(0); if (LI.isVolatile()) return 0; - if (ConstantPointerRef *CPR = dyn_cast(Op)) - Op = CPR->getValue(); + if (Constant *C = dyn_cast(Op)) + if (C->isNullValue()) // load null -> 0 + return ReplaceInstUsesWith(LI, Constant::getNullValue(LI.getType())); + else if (ConstantPointerRef *CPR = dyn_cast(C)) + Op = CPR->getValue(); // Instcombine load (constant global) into the value loaded... if (GlobalVariable *GV = dyn_cast(Op)) @@ -2624,6 +2862,27 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { if (GV->isConstant() && !GV->isExternal()) if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE)) return ReplaceInstUsesWith(LI, V); + + // load (cast X) --> cast (load X) iff safe + if (CastInst *CI = dyn_cast(Op)) { + const Type *DestPTy = cast(CI->getType())->getElementType(); + if (const PointerType *SrcTy = + dyn_cast(CI->getOperand(0)->getType())) { + const Type *SrcPTy = SrcTy->getElementType(); + if (TD->getTypeSize(SrcPTy) == TD->getTypeSize(DestPTy) && + (SrcPTy->isInteger() || isa(SrcPTy)) && + (DestPTy->isInteger() || isa(DestPTy))) { + // Okay, we are casting from one integer or pointer type to another of + // the same size. Instead of casting the pointer before the load, cast + // the result of the loaded value. + Value *NewLoad = InsertNewInstBefore(new LoadInst(CI->getOperand(0), + CI->getName()), LI); + // Now cast the result of the load. + return new CastInst(NewLoad, LI.getType()); + } + } + } + return 0; } @@ -2675,7 +2934,10 @@ bool InstCombiner::runOnFunction(Function &F) { bool Changed = false; TD = &getAnalysis(); - WorkList.insert(WorkList.end(), inst_begin(F), inst_end(F)); + for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { + WorkList.push_back(&*i); + } + while (!WorkList.empty()) { Instruction *I = WorkList.back(); // Get an instruction from the worklist