[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