diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index a65b8344954..956bb1e0139 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -4623,24 +4623,38 @@ static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) { static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) { User *CI = cast(LI.getOperand(0)); + Value *CastOp = CI->getOperand(0); const Type *DestPTy = cast(CI->getType())->getElementType(); - if (const PointerType *SrcTy = - dyn_cast(CI->getOperand(0)->getType())) { + if (const PointerType *SrcTy = dyn_cast(CastOp->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.isVolatile()),LI); - // Now cast the result of the load. - return new CastInst(NewLoad, LI.getType()); + + if (DestPTy->isInteger() || isa(DestPTy)) { + // If the source is an array, the code below will not succeed. Check to + // see if a trivial 'gep P, 0, 0' will help matters. Only do this for + // constants. + if (const ArrayType *ASrcTy = dyn_cast(SrcPTy)) + if (Constant *CSrc = dyn_cast(CastOp)) + if (ASrcTy->getNumElements() != 0) { + std::vector Idxs(2, Constant::getNullValue(Type::IntTy)); + CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs); + SrcTy = cast(CastOp->getType()); + SrcPTy = SrcTy->getElementType(); + } + + if ((SrcPTy->isInteger() || isa(SrcPTy)) && + IC.getTargetData().getTypeSize(SrcPTy) == + IC.getTargetData().getTypeSize(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(CastOp, + CI->getName(), + LI.isVolatile()),LI); + // Now cast the result of the load. + return new CastInst(NewLoad, LI.getType()); + } } } return 0;