diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index d43011da5bc..8d353c8063a 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -2947,6 +2947,30 @@ static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) { return C; } +static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) { + User *CI = cast(LI.getOperand(0)); + + const Type *DestPTy = cast(CI->getType())->getElementType(); + if (const PointerType *SrcTy = + dyn_cast(CI->getOperand(0)->getType())) { + const Type *SrcPTy = SrcTy->getElementType(); + if (SrcPTy->isSized() && DestPTy->isSized() && + IC.getTargetData().getTypeSize(SrcPTy) == + IC.getTargetData().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 = IC.InsertNewInstBefore(new LoadInst(CI->getOperand(0), + CI->getName()), LI); + // Now cast the result of the load. + return new CastInst(NewLoad, LI.getType()); + } + } + return 0; +} + Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { Value *Op = LI.getOperand(0); if (LI.isVolatile()) return 0; @@ -2964,33 +2988,21 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { // Instcombine load (constantexpr_GEP global, 0, ...) into the value loaded... if (ConstantExpr *CE = dyn_cast(Op)) - if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOpcode() == Instruction::GetElementPtr) { if (ConstantPointerRef *G=dyn_cast(CE->getOperand(0))) if (GlobalVariable *GV = dyn_cast(G->getValue())) if (GV->isConstant() && !GV->isExternal()) if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE)) return ReplaceInstUsesWith(LI, V); + } else if (CE->getOpcode() == Instruction::Cast) { + if (Instruction *Res = InstCombineLoadCast(*this, LI)) + return Res; + } // 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 (SrcPTy->isSized() && DestPTy->isSized() && - 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()); - } - } - } + if (CastInst *CI = dyn_cast(Op)) + if (Instruction *Res = InstCombineLoadCast(*this, LI)) + return Res; return 0; }