[llvm-commits] [llvm] r123563 - in /llvm/trunk: lib/Transforms/IPO/GlobalOpt.cpp test/Transforms/GlobalOpt/static-ctor-bitcast.ll

Owen Anderson resistor at mac.com
Sat Jan 15 20:33:33 PST 2011


Author: resistor
Date: Sat Jan 15 22:33:33 2011
New Revision: 123563

URL: http://llvm.org/viewvc/llvm-project?rev=123563&view=rev
Log:
Improve the safety of my globalopt enhancement by ensuring that the bitcast
of the stored value to the new store type is always.  Also, add a testcase.

Added:
    llvm/trunk/test/Transforms/GlobalOpt/static-ctor-bitcast.ll
Modified:
    llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp

Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=123563&r1=123562&r2=123563&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Sat Jan 15 22:33:33 2011
@@ -2358,21 +2358,31 @@
           
           const Type *NewTy=cast<PointerType>(Ptr->getType())->getElementType();
           
-          // A bitcast'd pointer implicitly points to the first field of a
-          // struct.  Insert implicity "gep @x, 0, 0, ..." until we get down
-          // to the first concrete member.
-          // FIXME: This could be extended to work for arrays as well.
-          while (const StructType *STy = dyn_cast<StructType>(NewTy)) {
-            NewTy = STy->getTypeAtIndex(0U);
-            
-            const IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
-            Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
-            Constant * const IdxList[] = {IdxZero, IdxZero};
+          // In order to push the bitcast onto the stored value, a bitcast
+          // from NewTy to Val's type must be legal.  If it's not, we can try
+          // introspecting NewTy to find a legal conversion.
+          while (!Val->getType()->canLosslesslyBitCastTo(NewTy)) {
+            // If NewTy is a struct, we can convert the pointer to the struct
+            // into a pointer to its first member.
+            // FIXME: This could be extended to support arrays as well.
+            if (const StructType *STy = dyn_cast<StructType>(NewTy)) {
+              NewTy = STy->getTypeAtIndex(0U);
+
+              const IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
+              Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
+              Constant * const IdxList[] = {IdxZero, IdxZero};
+
+              Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList, 2);
             
-            Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList, 2);
+            // If we can't improve the situation by introspecting NewTy,
+            // we have to give up.
+            } else {
+              return 0;
+            }
           }
           
-          if (!isa<PointerType>(NewTy)) return false;
+          // If we found compatible types, go ahead and push the bitcast
+          // onto the stored value.
           Val = ConstantExpr::getBitCast(Val, NewTy);
         }
           

Added: llvm/trunk/test/Transforms/GlobalOpt/static-ctor-bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/static-ctor-bitcast.ll?rev=123563&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/static-ctor-bitcast.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/static-ctor-bitcast.ll Sat Jan 15 22:33:33 2011
@@ -0,0 +1,59 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0.0"
+
+%0 = type { i8*, i8* }
+%1 = type { i8*, i8*, i32, i32, i8*, i64 }
+%2 = type { i32, void ()* }
+%struct.A = type { i32 }
+%struct.B = type { i32 (...)**, i8*, [4 x i8] }
+
+ at y = global i8 0, align 1
+ at x = global %struct.B zeroinitializer, align 8
+ at _ZTV1B = weak_odr unnamed_addr constant [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* null, i8* bitcast (%1* @_ZTI1B to i8*)]
+ at _ZTVN10__cxxabiv121__vmi_class_type_infoE = external global i8*
+ at _ZTS1B = weak_odr constant [3 x i8] c"1B\00"
+ at _ZTVN10__cxxabiv117__class_type_infoE = external global i8*
+ at _ZTS1A = weak_odr constant [3 x i8] c"1A\00"
+ at _ZTI1A = weak_odr unnamed_addr constant %0 { i8* bitcast (i8** getelementptr inbounds (i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8]* @_ZTS1A, i32 0, i32 0) }
+ at _ZTI1B = weak_odr unnamed_addr constant %1 { i8* bitcast (i8** getelementptr inbounds (i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8]* @_ZTS1B, i32 0, i32 0), i32 0, i32 1, i8* bitcast (%0* @_ZTI1A to i8*), i64 -6141 }
+ at _ZTT1B = weak_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 1, i64 0) to i8*)]
+ at llvm.global_ctors = appending global [1 x %2] [%2 { i32 65535, void ()* @_GLOBAL__I_a }]
+
+; CHECK-NOT: __cxx_global_var_init
+define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
+entry:
+  call void @_ZN1BC1Ev(%struct.B* @x)
+  ret void
+}
+
+; CHECK-NOT: _ZN1BC1Ev
+define linkonce_odr unnamed_addr void @_ZN1BC1Ev(%struct.B* %this) inlinehint ssp align 2 {
+entry:
+  %0 = bitcast %struct.B* %this to i8*
+  %1 = getelementptr inbounds i8* %0, i64 16
+  %2 = bitcast i8* %1 to %struct.A*
+  call void @_ZN1AC2Ev(%struct.A* %2)
+  %3 = bitcast %struct.B* %this to i8***
+  store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 1, i64 0), i8*** %3
+  ret void
+}
+
+; CHECK-NOT: _ZN1AC2Ev
+define linkonce_odr unnamed_addr void @_ZN1AC2Ev(%struct.A* %this) nounwind ssp align 2 {
+entry:
+  %0 = ptrtoint %struct.A* %this to i64
+  %sub = sub i64 %0, ptrtoint (%struct.B* @x to i64)
+  %div = udiv i64 %sub, 8
+  %conv = trunc i64 %div to i8
+  store i8 %conv, i8* @y, align 1
+  ret void
+}
+
+; CHECK-NOT: _GLOBAL__I_a
+define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+entry:
+  call void @__cxx_global_var_init()
+  ret void
+}





More information about the llvm-commits mailing list