mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-27 12:26:08 +00:00
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 ; <int (...)***> [#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 ; <int (...)***> [#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"*)**) ; <int ("struct.std::bad_typeid"*)*> [#uses=1] %tmp.6 = call int %tmp.5( "struct.std::bad_typeid"* %x ) ; <int> [#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
This commit is contained in:
@@ -2947,6 +2947,30 @@ static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) {
|
|||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) {
|
||||||
|
User *CI = cast<User>(LI.getOperand(0));
|
||||||
|
|
||||||
|
const Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
|
||||||
|
if (const PointerType *SrcTy =
|
||||||
|
dyn_cast<PointerType>(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<PointerType>(SrcPTy)) &&
|
||||||
|
(DestPTy->isInteger() || isa<PointerType>(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) {
|
Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
|
||||||
Value *Op = LI.getOperand(0);
|
Value *Op = LI.getOperand(0);
|
||||||
if (LI.isVolatile()) return 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...
|
// Instcombine load (constantexpr_GEP global, 0, ...) into the value loaded...
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op))
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op))
|
||||||
if (CE->getOpcode() == Instruction::GetElementPtr)
|
if (CE->getOpcode() == Instruction::GetElementPtr) {
|
||||||
if (ConstantPointerRef *G=dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
|
if (ConstantPointerRef *G=dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
|
||||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getValue()))
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getValue()))
|
||||||
if (GV->isConstant() && !GV->isExternal())
|
if (GV->isConstant() && !GV->isExternal())
|
||||||
if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE))
|
if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE))
|
||||||
return ReplaceInstUsesWith(LI, V);
|
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
|
// load (cast X) --> cast (load X) iff safe
|
||||||
if (CastInst *CI = dyn_cast<CastInst>(Op)) {
|
if (CastInst *CI = dyn_cast<CastInst>(Op))
|
||||||
const Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
|
if (Instruction *Res = InstCombineLoadCast(*this, LI))
|
||||||
if (const PointerType *SrcTy =
|
return Res;
|
||||||
dyn_cast<PointerType>(CI->getOperand(0)->getType())) {
|
|
||||||
const Type *SrcPTy = SrcTy->getElementType();
|
|
||||||
if (SrcPTy->isSized() && DestPTy->isSized() &&
|
|
||||||
TD->getTypeSize(SrcPTy) == TD->getTypeSize(DestPTy) &&
|
|
||||||
(SrcPTy->isInteger() || isa<PointerType>(SrcPTy)) &&
|
|
||||||
(DestPTy->isInteger() || isa<PointerType>(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user