From b89e071aea07022c0240491b380a23958692890c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 13 Jul 2004 01:49:43 +0000 Subject: [PATCH] Factor some code to handle "load (constantexpr cast foo)" just like "load (cast foo)". This allows us to compile C++ code like this: class Bclass { public: virtual int operator()() { return 666; } }; class Dclass: public Bclass { public: virtual int operator()() { return 667; } } ; int main(int argc, char** argv) { Dclass x; return x(); } Into this: int %main(int %argc, sbyte** %argv) { entry: call void %__main( ) ret int 667 } Instead of this: int %main(int %argc, sbyte** %argv) { entry: %x = alloca "struct.std::bad_typeid" ; <"struct.std::bad_typeid"*> [#uses=3] call void %__main( ) %tmp.1.i.i = getelementptr "struct.std::bad_typeid"* %x, uint 0, uint 0, uint 0 ; [#uses=1] store int (...)** getelementptr ([3 x int (...)*]* %vtable for Bclass, int 0, long 2), int (...)*** %tmp.1.i.i %tmp.3.i = getelementptr "struct.std::bad_typeid"* %x, int 0, uint 0, uint 0 ; [#uses=1] store int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2), int (...)*** %tmp.3.i %tmp.5 = load int ("struct.std::bad_typeid"*)** cast (int (...)** getelementptr ([3 x int (...)*]* %vtable for Dclass, int 0, long 2) to int ("struct.std::bad_typeid"*)**) ; [#uses=1] %tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; [#uses=1] ret int %tmp.6 ret int 0 } In order words, we now resolve the virtual function call. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14783 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) 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; }