[llvm-commits] [llvm] r160664 - in /llvm/trunk: lib/Transforms/IPO/GlobalOpt.cpp test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll

Nick Lewycky nlewycky at google.com
Tue Jul 24 14:28:57 PDT 2012


Thanks, I'm able to reproduce it and have a fix I'm testing. Sorry for the
breakage!!

On 24 July 2012 09:05, David Dean <david_dean at apple.com> wrote:

> Nick, this seems to be breaking self-hosting on darwin:
>
> While deleting: %"class.std::basic_string"* %temp.lvalue
> Use still stuck around after Def is destroyed:  call void
> @_ZNSsD1Ev(%"class.std::basic_string"* %temp.lvalue)
> Use still stuck around after Def is destroyed:  call void
> @_ZNK4llvm9StringRefcvSsEv(%"class.std::basic_string"* sret %temp.lvalue,
> %"class.llvm::StringRef"* %coerce)
> Assertion failed: (use_empty() && "Uses remain when a value is
> destroyed!"), function ~Value, file
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/llvm/lib/VMCore/Value.cpp,
> line 75.
> 0  clang             0x000000010159a472
> llvm::SmallVectorImpl<char>::swap(llvm::SmallVectorImpl<char>&) + 14450
> 1  clang             0x000000010159a954
> llvm::SmallVectorImpl<char>::swap(llvm::SmallVectorImpl<char>&) + 15700
> 2  libsystem_c.dylib 0x00007fff9135fcfa _sigtramp + 26
> 3  libsystem_c.dylib 0x0000000000000002 _sigtramp + 18446603338079929122
> 4  clang             0x000000010159a6b6
> llvm::SmallVectorImpl<char>::swap(llvm::SmallVectorImpl<char>&) + 15030
> 5  clang             0x000000010159a691
> llvm::SmallVectorImpl<char>::swap(llvm::SmallVectorImpl<char>&) + 14993
> 6  clang             0x000000010154d44d
> llvm::enable_if<llvm::hashing::detail::is_hashable_data<llvm::Type* const>,
> llvm::hash_code>::type
> llvm::hashing::detail::hash_combine_range_impl<llvm::Type*
> const>(llvm::Type* const*, llvm::Type* const*) + 7101
> 7  clang             0x000000010151b20e
> std::_Rb_tree<std::pair<llvm::PointerType*, llvm::InlineAsmKeyType>,
> std::pair<std::pair<llvm::PointerType*, llvm::InlineAsmKeyType> const,
> llvm::InlineAsm*>, std::_Select1st<std::pair<std::pair<llvm::PointerType*,
> llvm::InlineAsmKeyType> const, llvm::InlineAsm*> >,
> std::less<std::pair<llvm::PointerType*, llvm::InlineAsmKeyType> >,
> std::allocator<std::pair<std::pair<llvm::PointerType*,
> llvm::InlineAsmKeyType> const, llvm::InlineAsm*> >
> >::_M_insert_unique(std::pair<std::pair<llvm::PointerType*,
> llvm::InlineAsmKeyType> const, llvm::InlineAsm*> const&) + 21246
> 8  clang             0x0000000100ad9e54 std::vector<llvm::Function*,
> std::allocator<llvm::Function*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::Function**,
> std::vector<llvm::Function*, std::allocator<llvm::Function*> > >,
> llvm::Function* const&) + 20532
> 9  clang             0x0000000100ad7506 std::vector<llvm::Function*,
> std::allocator<llvm::Function*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::Function**,
> std::vector<llvm::Function*, std::allocator<llvm::Function*> > >,
> llvm::Function* const&) + 9958
> 10 clang             0x0000000100ad5c26 std::vector<llvm::Function*,
> std::allocator<llvm::Function*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::Function**,
> std::vector<llvm::Function*, std::allocator<llvm::Function*> > >,
> llvm::Function* const&) + 3590
> 11 clang             0x000000010153d646 std::vector<llvm::StructType*,
> std::allocator<llvm::StructType*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::StructType**,
> std::vector<llvm::StructType*, std::allocator<llvm::StructType*> > >,
> llvm::StructType* const&) + 31510
> 12 clang             0x000000010153dc09 std::vector<llvm::StructType*,
> std::allocator<llvm::StructType*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::StructType**,
> std::vector<llvm::StructType*, std::allocator<llvm::StructType*> > >,
> llvm::StructType* const&) + 32985
> 13 clang             0x000000010153dded std::vector<llvm::StructType*,
> std::allocator<llvm::StructType*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::StructType**,
> std::vector<llvm::StructType*, std::allocator<llvm::StructType*> > >,
> llvm::StructType* const&) + 33469
> 14 clang             0x000000010016256a
> std::vector<clang::serialization::ModuleFile*,
> std::allocator<clang::serialization::ModuleFile*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<clang::serialization::ModuleFile**,
> std::vector<clang::serialization::ModuleFile*,
> std::allocator<clang::serialization::ModuleFile*> > >,
> clang::serialization::ModuleFile* const&) + 7738
> 15 clang             0x0000000100244dca llvm::ParseIR(llvm::MemoryBuffer*,
> llvm::SMDiagnostic&, llvm::LLVMContext&) + 2010
> 16 clang             0x000000010027b9b4
> std::vector<std::pair<llvm::WeakVH, llvm::Constant*>,
> std::allocator<std::pair<llvm::WeakVH, llvm::Constant*> >
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::pair<llvm::WeakVH,
> llvm::Constant*>*, std::vector<std::pair<llvm::WeakVH, llvm::Constant*>,
> std::allocator<std::pair<llvm::WeakVH, llvm::Constant*> > > >,
> std::pair<llvm::WeakVH, llvm::Constant*> const&) + 53524
> 17 clang             0x0000000100243a00 std::vector<clang::CXXRecordDecl
> const*, std::allocator<clang::CXXRecordDecl const*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<clang::CXXRecordDecl const**,
> std::vector<clang::CXXRecordDecl const*,
> std::allocator<clang::CXXRecordDecl const*> > >, clang::CXXRecordDecl
> const* const&) + 6224
> 18 clang             0x000000010004f0b8
> llvm::SmallVectorImpl<clang::FileEntry
> const*>::operator=(llvm::SmallVectorImpl<clang::FileEntry const*> const&) +
> 10184
> 19 clang             0x0000000100024d5f
> std::vector<clang::CompilerInstance*,
> std::allocator<clang::CompilerInstance*>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<clang::CompilerInstance**,
> std::vector<clang::CompilerInstance*,
> std::allocator<clang::CompilerInstance*> > >, clang::CompilerInstance*
> const&) + 16623
> 20 clang             0x000000010000b40a std::_Rb_tree<std::string,
> std::string, std::_Identity<std::string>, std::less<std::string>,
> std::allocator<std::string> >::_M_insert_unique(std::string const&) + 3978
> 21 clang             0x0000000100000e1a
> 22 clang             0x0000000100007e6c std::vector<std::string,
> std::allocator<std::string>
> >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::string*,
> std::vector<std::string, std::allocator<std::string> > >, std::string
> const&) + 4124
> 23 clang             0x0000000100000b34
> 24 clang             0x000000000000004f
> Stack dump:
> 0.      Program arguments:
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/host-compiler/bin/clang
> -cc1 -triple x86_64-apple-macosx10.7.0 -emit-obj -disable-free
> -main-file-name PrettyStackTrace.cpp -pic-level 2 -mdisable-fp-elim
> -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version
> 127.2.1 -coverage-file
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support/Release+Asserts/PrettyStackTrace.o
> -resource-dir
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/host-compiler/bin/../lib/clang/3.2
> -dependency-file
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support/Release+Asserts/PrettyStackTrace.d.tmp
> -MP -MT
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support/Release+Asserts/PrettyStackTrace.o
> -MT
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support/Release+Asserts/PrettyStackTrace.d
> -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS
> -D __STDC_LIMIT_MACROS -I
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/include
> -I
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support
> -I
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/llvm/include
> -I
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/llvm/lib/Support
> -fmodule-cache-path
> /var/folders/c0/p42p46x90pz38sc3mpntqhh80000gp/T/clang-module-cache -O3
> -Woverloaded-virtual -Wcast-qual -Wall -W -Wno-unused-parameter
> -Wwrite-strings -Wcovered-switch-default -fconst-strings -fdeprecated-macro
> -fdebug-compilation-dir
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support
> -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden
> -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.7.0
> -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties
> -fno-common -fdiagnostics-show-option -o
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/clang-build/lib/Support/Release+Asserts/PrettyStackTrace.o
> -x c++
> /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/llvm/lib/Support/PrettyStackTrace.cpp
> 1.      <eof> parser at end of file
> 2.      Per-module optimization passes
> 3.      Running pass 'Global Variable Optimizer' on module
> '/Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin11-RA/llvm/lib/Support/PrettyStackTrace.cpp'.
> clang: error: unable to execute command: Illegal instruction: 4
> clang: error: clang frontend command failed due to signal (use -v to see
> invocation)
> clang version 3.2 (trunk 160664)
>
>
> I've attached the preprocessed source and run script to reproduce.
>
>
>
>
> On 24 Jul 2012, at 12:21 AM, Nick Lewycky <nicholas at mxc.ca> wrote:
>
> > Author: nicholas
> > Date: Tue Jul 24 02:21:08 2012
> > New Revision: 160664
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=160664&view=rev
> > Log:
> > Teach globalopt to not nuke all stores to globals. Keep them around of
> they
> > might be deliberate "one time" leaks, so that leak checkers can find
> them.
> > This is a reapply of r160602 with the fix that this time I'm committing
> the
> > code I thought I was committing last time; the I->eraseFromParent() goes
> > *after* the break out of the loop.
> >
> > Added:
> >    llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll
> > Modified:
> >    llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> >
>  llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll
> >
> > Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=160664&r1=160663&r2=160664&view=diff
> >
> ==============================================================================
> > --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> > +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Tue Jul 24 02:21:08 2012
> > @@ -296,6 +296,165 @@
> >   return false;
> > }
> >
> > +/// isLeakCheckerRoot - Is this global variable possibly used by a leak
> checker
> > +/// as a root?  If so, we might not really want to eliminate the stores
> to it.
> > +static bool isLeakCheckerRoot(GlobalVariable *GV) {
> > +  // A global variable is a root if it is a pointer, or could plausibly
> contain
> > +  // a pointer.  There are two challenges; one is that we could have a
> struct
> > +  // the has an inner member which is a pointer.  We recurse through
> the type to
> > +  // detect these (up to a point).  The other is that we may actually
> be a union
> > +  // of a pointer and another type, and so our LLVM type is an integer
> which
> > +  // gets converted into a pointer, or our type is an [i8 x #] with a
> pointer
> > +  // potentially contained here.
> > +
> > +  if (GV->hasPrivateLinkage())
> > +    return false;
> > +
> > +  SmallVector<Type *, 4> Types;
> > +  Types.push_back(cast<PointerType>(GV->getType())->getElementType());
> > +
> > +  unsigned Limit = 20;
> > +  do {
> > +    Type *Ty = Types.pop_back_val();
> > +    switch (Ty->getTypeID()) {
> > +      default: break;
> > +      case Type::PointerTyID: return true;
> > +      case Type::ArrayTyID:
> > +      case Type::VectorTyID: {
> > +        SequentialType *STy = cast<SequentialType>(Ty);
> > +        Types.push_back(STy->getElementType());
> > +        break;
> > +      }
> > +      case Type::StructTyID: {
> > +        StructType *STy = cast<StructType>(Ty);
> > +        if (STy->isOpaque()) return true;
> > +        for (StructType::element_iterator I = STy->element_begin(),
> > +                 E = STy->element_end(); I != E; ++I) {
> > +          Type *InnerTy = *I;
> > +          if (isa<PointerType>(InnerTy)) return true;
> > +          if (isa<CompositeType>(InnerTy))
> > +            Types.push_back(InnerTy);
> > +        }
> > +        break;
> > +      }
> > +    }
> > +    if (--Limit == 0) return true;
> > +  } while (!Types.empty());
> > +  return false;
> > +}
> > +
> > +/// Given a value that is stored to a global but never read, determine
> whether
> > +/// it's safe to remove the store and the chain of computation that
> feeds the
> > +/// store.
> > +static bool IsSafeComputationToRemove(Value *V) {
> > +  do {
> > +    if (isa<Constant>(V))
> > +      return true;
> > +    if (!V->hasOneUse())
> > +      return false;
> > +    if (isa<LoadInst>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
> > +      return false;
> > +    if (isAllocationFn(V))
> > +      return true;
> > +
> > +    Instruction *I = cast<Instruction>(V);
> > +    if (I->mayHaveSideEffects())
> > +      return false;
> > +    if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
> > +      if (!GEP->hasAllConstantIndices())
> > +        return false;
> > +    } else if (I->getNumOperands() != 1) {
> > +      return false;
> > +    }
> > +
> > +    V = I->getOperand(0);
> > +  } while (1);
> > +}
> > +
> > +/// CleanupPointerRootUsers - This GV is a pointer root.  Loop over all
> users
> > +/// of the global and clean up any that obviously don't assign the
> global a
> > +/// value that isn't dynamically allocated.
> > +///
> > +static bool CleanupPointerRootUsers(GlobalVariable *GV) {
> > +  // A brief explanation of leak checkers.  The goal is to find bugs
> where
> > +  // pointers are forgotten, causing an accumulating growth in memory
> > +  // usage over time.  The common strategy for leak checkers is to
> whitelist the
> > +  // memory pointed to by globals at exit.  This is popular because it
> also
> > +  // solves another problem where the main thread of a C++ program may
> shut down
> > +  // before other threads that are still expecting to use those
> globals.  To
> > +  // handle that case, we expect the program may create a singleton and
> never
> > +  // destroy it.
> > +
> > +  bool Changed = false;
> > +
> > +  // If Dead[n].first is the only use of a malloc result, we can delete
> its
> > +  // chain of computation and the store to the global in Dead[n].second.
> > +  SmallVector<std::pair<Instruction *, Instruction *>, 32> Dead;
> > +
> > +  // Constants can't be pointers to dynamically allocated memory.
> > +  for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
> > +       UI != E;) {
> > +    User *U = *UI++;
> > +    if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
> > +      Value *V = SI->getValueOperand();
> > +      if (isa<Constant>(V)) {
> > +        Changed = true;
> > +        SI->eraseFromParent();
> > +      } else if (Instruction *I = dyn_cast<Instruction>(V)) {
> > +        if (I->hasOneUse())
> > +          Dead.push_back(std::make_pair(I, SI));
> > +      }
> > +    } else if (MemSetInst *MSI = dyn_cast<MemSetInst>(U)) {
> > +      if (isa<Constant>(MSI->getValue())) {
> > +        Changed = true;
> > +        MSI->eraseFromParent();
> > +      } else if (Instruction *I =
> dyn_cast<Instruction>(MSI->getValue())) {
> > +        if (I->hasOneUse())
> > +          Dead.push_back(std::make_pair(I, MSI));
> > +      }
> > +    } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(U)) {
> > +      GlobalVariable *MemSrc =
> dyn_cast<GlobalVariable>(MTI->getSource());
> > +      if (MemSrc && MemSrc->isConstant()) {
> > +        Changed = true;
> > +        MTI->eraseFromParent();
> > +      } else if (Instruction *I = dyn_cast<Instruction>(MemSrc)) {
> > +        if (I->hasOneUse())
> > +          Dead.push_back(std::make_pair(I, MTI));
> > +      }
> > +    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
> > +      if (CE->use_empty()) {
> > +        CE->destroyConstant();
> > +        Changed = true;
> > +      }
> > +    } else if (Constant *C = dyn_cast<Constant>(U)) {
> > +      if (SafeToDestroyConstant(C)) {
> > +        C->destroyConstant();
> > +        // This could have invalidated UI, start over from scratch.
> > +        Dead.clear();
> > +        CleanupPointerRootUsers(GV);
> > +        return true;
> > +      }
> > +    }
> > +  }
> > +
> > +  for (int i = 0, e = Dead.size(); i != e; ++i) {
> > +    if (IsSafeComputationToRemove(Dead[i].first)) {
> > +      Dead[i].second->eraseFromParent();
> > +      Instruction *I = Dead[i].first;
> > +      do {
> > +        Instruction *J = dyn_cast<Instruction>(I->getOperand(0));
> > +        if (!J)
> > +          break;
> > +        I->eraseFromParent();
> > +        I = J;
> > +      } while (!isAllocationFn(I));
> > +      I->eraseFromParent();
> > +    }
> > +  }
> > +
> > +  return Changed;
> > +}
> > +
> > /// CleanupConstantGlobalUsers - We just marked GV constant.  Loop over
> all
> > /// users of the global, cleaning up the obvious ones.  This is largely
> just a
> > /// quick scan over the use list to clean up the easy and obvious cruft.
>  This
> > @@ -812,13 +971,18 @@
> >   // If we nuked all of the loads, then none of the stores are needed
> either,
> >   // nor is the global.
> >   if (AllNonStoreUsesGone) {
> > -    DEBUG(dbgs() << "  *** GLOBAL NOW DEAD!\n");
> > -    CleanupConstantGlobalUsers(GV, 0, TD, TLI);
> > +    if (isLeakCheckerRoot(GV)) {
> > +      Changed |= CleanupPointerRootUsers(GV);
> > +    } else {
> > +      Changed = true;
> > +      CleanupConstantGlobalUsers(GV, 0, TD, TLI);
> > +    }
> >     if (GV->use_empty()) {
> > +      DEBUG(dbgs() << "  *** GLOBAL NOW DEAD!\n");
> > +      Changed = true;
> >       GV->eraseFromParent();
> >       ++NumDeleted;
> >     }
> > -    Changed = true;
> >   }
> >   return Changed;
> > }
> > @@ -1794,10 +1958,15 @@
> >   if (!GS.isLoaded) {
> >     DEBUG(dbgs() << "GLOBAL NEVER LOADED: " << *GV);
> >
> > -    // Delete any stores we can find to the global.  We may not be able
> to
> > -    // make it completely dead though.
> > -    bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer(),
> > -                                              TD, TLI);
> > +    bool Changed;
> > +    if (isLeakCheckerRoot(GV)) {
> > +      // Delete any constant stores to the global.
> > +      Changed = CleanupPointerRootUsers(GV);
> > +    } else {
> > +      // Delete any stores we can find to the global.  We may not be
> able to
> > +      // make it completely dead though.
> > +      Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer(),
> TD, TLI);
> > +    }
> >
> >     // If the global is dead now, delete it.
> >     if (GV->use_empty()) {
> > @@ -1845,7 +2014,7 @@
> >
> >         if (GV->use_empty()) {
> >           DEBUG(dbgs() << "   *** Substituting initializer allowed us to
> "
> > -                << "simplify all users and delete global!\n");
> > +                       << "simplify all users and delete global!\n");
> >           GV->eraseFromParent();
> >           ++NumDeleted;
> >         } else {
> >
> > Modified:
> llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll?rev=160664&r1=160663&r2=160664&view=diff
> >
> ==============================================================================
> > ---
> llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll
> (original)
> > +++
> llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll
> Tue Jul 24 02:21:08 2012
> > @@ -17,7 +17,7 @@
> >   %2 = sext i32 %1 to i64                         ; <i64> [#uses=1]
> >   %3 = mul i64 %2, ptrtoint (%struct.strchartype* getelementptr
> (%struct.strchartype* null, i64 1) to i64) ; <i64> [#uses=1]
> >   %4 = tail call i8* @malloc(i64 %3)              ; <i8*> [#uses=1]
> > -; CHECK: call i8* @malloc(i64
> > +; CHECK-NOT: call i8* @malloc(i64
> >   %5 = bitcast i8* %4 to %struct.strchartype*     ;
> <%struct.strchartype*> [#uses=1]
> >   store %struct.strchartype* %5, %struct.strchartype** @chartypes, align
> 8
> >   ret void
> >
> > Added: llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll?rev=160664&view=auto
> >
> ==============================================================================
> > --- llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll
> (added)
> > +++ llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll
> Tue Jul 24 02:21:08 2012
> > @@ -0,0 +1,19 @@
> > +; RUN: opt -globalopt -S -o - < %s | FileCheck %s
> > +
> > + at test1 = internal global i8* null
> > +
> > +define void @test1a() {
> > +; CHECK: @test1a
> > +; CHECK-NOT: store
> > +; CHECK-NEXT: ret void
> > +  store i8* null, i8** @test1
> > +  ret void
> > +}
> > +
> > +define void @test1b(i8* %p) {
> > +; CHECK: @test1b
> > +; CHECK-NEXT: store
> > +; CHECK-NEXT: ret void
> > +  store i8* %p, i8** @test1
> > +  ret void
> > +}
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>
> -David
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120724/f4e2d040/attachment.html>


More information about the llvm-commits mailing list