[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Mon Jul 12 18:49:54 PDT 2004
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.221 -> 1.222
---
Log message:
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.
---
Diffs of the changes: (+32 -20)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.221 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.222
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.221 Tue Jul 6 14:28:42 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jul 12 20:49:43 2004
@@ -2947,6 +2947,30 @@
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) {
Value *Op = LI.getOperand(0);
if (LI.isVolatile()) return 0;
@@ -2964,33 +2988,21 @@
// Instcombine load (constantexpr_GEP global, 0, ...) into the value loaded...
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 (GlobalVariable *GV = dyn_cast<GlobalVariable>(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<CastInst>(Op)) {
- 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() &&
- 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());
- }
- }
- }
+ if (CastInst *CI = dyn_cast<CastInst>(Op))
+ if (Instruction *Res = InstCombineLoadCast(*this, LI))
+ return Res;
return 0;
}
More information about the llvm-commits
mailing list