[llvm] r212337 - GlobalDCE: Delete available_externally initializers if it allows removing the value the initializer is referring to.

Pete Cooper peter_cooper at apple.com
Tue Jul 8 10:03:02 PDT 2014


> On Jul 7, 2014, at 10:28 PM, Benjamin Kramer <benny.kra at gmail.com> wrote:
> 
> 
> On 07.07.2014, at 20:20, Pete Cooper <pete.cooper at gmail.com> wrote:
> 
>> Hey Ben
>> 
>> This is crashing our test suite.  Mind taking a look?  This may be related to what Richard has just pointed out too.
> 
> I think this is something different. Feel free to revert if this is blocking you in the meantime.
Thanks Ben.  I’m able to repro the crash for the attached file, and have it pass, just by reverting.

Going to do that now.

Thanks,
Pete
> 
> - Ben
> 
>> 
>> Attached a reduced test which crashes the following "opt dce.ll -globaldce -o file.bc”
>> 
>> Cheers,
>> Pete
>> 
>> 
>> 
>> 
>> On Fri, Jul 4, 2014 at 1:36 PM, Benjamin Kramer <benny.kra at googlemail.com> wrote:
>> Author: d0k
>> Date: Fri Jul  4 07:36:05 2014
>> New Revision: 212337
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=212337&view=rev
>> Log:
>> GlobalDCE: Delete available_externally initializers if it allows removing the value the initializer is referring to.
>> 
>> This is useful for functions that are not actually available externally but
>> referenced by a vtable of some kind. Clang emits functions like this for the MS
>> ABI.
>> 
>> PR20182.
>> 
>> Modified:
>>    llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
>>    llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll
>> 
>> Modified: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp?rev=212337&r1=212336&r2=212337&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp (original)
>> +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp Fri Jul  4 07:36:05 2014
>> @@ -44,14 +44,19 @@ namespace {
>>     bool runOnModule(Module &M) override;
>> 
>>   private:
>> -    SmallPtrSet<GlobalValue*, 32> AliveGlobals;
>> +    SmallPtrSet<Constant *, 32> AliveGlobals;
>>     SmallPtrSet<Constant *, 8> SeenConstants;
>> +    SmallPtrSet<GlobalVariable *, 8> DiscardableGlobalInitializers;
>> 
>>     /// GlobalIsNeeded - mark the specific global value as needed, and
>>     /// recursively mark anything that it uses as also needed.
>>     void GlobalIsNeeded(GlobalValue *GV);
>>     void MarkUsedGlobalsAsNeeded(Constant *C);
>> 
>> +    /// \brief Checks if C is alive or is a ConstantExpr that refers to an alive
>> +    /// value.
>> +    bool ContainsUsedGlobal(Constant *C);
>> +
>>     bool RemoveUnusedGlobalValue(GlobalValue &GV);
>>   };
>> }
>> @@ -162,6 +167,19 @@ bool GlobalDCE::runOnModule(Module &M) {
>>       I->setAliasee(nullptr);
>>     }
>> 
>> +  // Look for available externally constants that we can turn into normal
>> +  // externals by deleting their initalizers. This allows us to remove other
>> +  // globals that are referenced by the initializer.
>> +  if (!DiscardableGlobalInitializers.empty()) {
>> +    for (GlobalVariable *GV : DiscardableGlobalInitializers) {
>> +      if (!ContainsUsedGlobal(GV->getInitializer())) {
>> +        GV->setInitializer(nullptr);
>> +        GV->setLinkage(GlobalValue::ExternalLinkage);
>> +        Changed = true;
>> +      }
>> +    }
>> +  }
>> +
>>   if (!DeadFunctions.empty()) {
>>     // Now that all interferences have been dropped, delete the actual objects
>>     // themselves.
>> @@ -209,8 +227,12 @@ void GlobalDCE::GlobalIsNeeded(GlobalVal
>>   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G)) {
>>     // If this is a global variable, we must make sure to add any global values
>>     // referenced by the initializer to the alive set.
>> -    if (GV->hasInitializer())
>> -      MarkUsedGlobalsAsNeeded(GV->getInitializer());
>> +    if (GV->hasInitializer()) {
>> +      if (GV->hasAvailableExternallyLinkage())
>> +        DiscardableGlobalInitializers.insert(GV);
>> +      else
>> +        MarkUsedGlobalsAsNeeded(GV->getInitializer());
>> +    }
>>   } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
>>     // The target of a global alias is needed.
>>     MarkUsedGlobalsAsNeeded(GA->getAliasee());
>> @@ -248,6 +270,21 @@ void GlobalDCE::MarkUsedGlobalsAsNeeded(
>>   }
>> }
>> 
>> +bool GlobalDCE::ContainsUsedGlobal(Constant *C) {
>> +  // C contains a used global If C is alive or we visited it while marking
>> +  // values alive.
>> +  if (AliveGlobals.count(C) || SeenConstants.count(C))
>> +    return true;
>> +
>> +  // Now check all operands of a ConstantExpr.
>> +  for (User::op_iterator I = C->op_begin(), E = C->op_end(); I != E; ++I) {
>> +    Constant *Op = dyn_cast<Constant>(*I);
>> +    if (Op && ContainsUsedGlobal(Op))
>> +      return true;
>> +  }
>> +  return false;
>> +}
>> +
>> // RemoveUnusedGlobalValue - Loop over all of the uses of the specified
>> // GlobalValue, looking for the constant pointer ref that may be pointing to it.
>> // If found, check to see if the constant pointer ref is safe to destroy, and if
>> 
>> Modified: llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll?rev=212337&r1=212336&r2=212337&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll (original)
>> +++ llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll Fri Jul  4 07:36:05 2014
>> @@ -1,10 +1,43 @@
>> -; RUN: opt < %s -globaldce -S | not grep test_
>> +; RUN: opt < %s -globaldce -S | FileCheck %s
>> 
>> ; test_function should not be emitted to the .s file.
>> +; CHECK-NOT: @test_function
>> define available_externally i32 @test_function() {
>>   ret i32 4
>> }
>> 
>> ; test_global should not be emitted to the .s file.
>> +; CHECK-NOT: @test_global
>> @test_global = available_externally global i32 4
>> 
>> +; CHECK: @x = external constant void ()*
>> + at x = available_externally constant void()* @f
>> +; CHECK: @y = external constant i32
>> + at y = available_externally constant i32 ptrtoint (void()* @g to i32)
>> +; @h is still alive, so don't remove the initializer too eagerly.
>> +; CHECK: @z = available_externally constant i8 ptrtoint (void (i8)* @h to i8)
>> + at z = available_externally constant i8 ptrtoint (void(i8)* @h to i8)
>> +
>> +; CHECK-NOT: @f
>> +define linkonce_odr void @f() {
>> +  ret void
>> +}
>> +
>> +; CHECK-NOT: @g
>> +define linkonce_odr void @g() {
>> +  ret void
>> +}
>> +
>> +; CHECK: define linkonce_odr void @h
>> +define linkonce_odr void @h(i8) {
>> +  ret void
>> +}
>> +
>> +define i32 @main() {
>> +  %f = load void()** @x
>> +  call void %f()
>> +  %g = load i32* @y
>> +  %h = load i8* @z
>> +  call void @h(i8 %h)
>> +  ret i32 %g
>> +}
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> 
>> <dce.ll>
> 
> 
> _______________________________________________
> 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/20140708/5f416f1c/attachment.html>


More information about the llvm-commits mailing list