This is an archive of the discontinued LLVM Phabricator instance.

[GlobalOpt] Simplify CleanupConstantGlobalUsers()
ClosedPublic

Authored by nikic on Dec 1 2021, 9:59 AM.

Details

Summary

This bases the CleanupConstantGlobalUsers() implementation around the ConstantFoldLoadFromConst() API. The general approach is that we discover all users while looking through casts, and then constant fold loads and drop stores and memintrinsics.

This avoids special cases and limitations in the previous implementation, which is also incompatible with opaque pointers. The result is a bit more powerful than before, because we now use more general load folding logic which can for example look through pointer bitcasts between different sizes. This is where the test changes come from, as we now fold more loads and can thus remove more globals.

Diff Detail

Event Timeline

nikic created this revision.Dec 1 2021, 9:59 AM
nikic requested review of this revision.Dec 1 2021, 9:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 1 2021, 9:59 AM
aeubanks added inline comments.Dec 1 2021, 10:57 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
307

is this true for non-inbounds GEPs?

334

even though Changed should be true if this returns true, still seems good to Changed |= ... here to prevent potential future issues

nikic updated this revision to Diff 391091.Dec 1 2021, 11:16 AM
nikic marked an inline comment as done.

Updated Changed with RecursivelyDeleteTriviallyDeadInstructions() call.

nikic added inline comments.Dec 1 2021, 11:18 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
307

Yes, because the result is either zero or the load is UB. This is similar to the logic in https://github.com/llvm/llvm-project/blob/b1bc627e7e9965e6ec15e106ee4b2c21f6c36923/llvm/lib/Analysis/ConstantFolding.cpp#L704.

aeubanks accepted this revision.Dec 1 2021, 11:24 AM
aeubanks added inline comments.
llvm/lib/Transforms/IPO/GlobalOpt.cpp
307

ah the langref clears that up, thanks

This revision is now accepted and ready to land.Dec 1 2021, 11:24 AM
This revision was landed with ongoing or failed builds.Dec 1 2021, 12:06 PM
This revision was automatically updated to reflect the committed changes.

It looks like the issue described in
https://bugs.llvm.org/show_bug.cgi?id=39751
stopped happening with this patch.

nikic added a comment.Dec 2 2021, 12:19 AM

It looks like the issue described in
https://bugs.llvm.org/show_bug.cgi?id=39751
stopped happening with this patch.

Thanks for the pointer. I committed the test case in https://github.com/llvm/llvm-project/commit/bc61e5e90b8db92aa5464d0565c8993b776df54d -- just need to remember that the issue can be closed once that's possible again :)

It looks like the issue described in
https://bugs.llvm.org/show_bug.cgi?id=39751
stopped happening with this patch.

Thanks for the pointer. I committed the test case in https://github.com/llvm/llvm-project/commit/bc61e5e90b8db92aa5464d0565c8993b776df54d -- just need to remember that the issue can be closed once that's possible again :)

Great, thanks!
Yes it's starting to pile up now. I have a list of things to do once it opens up somewhere, I can add PR39751 to my list and close it too.

Btw, I've seen a crash starting to happen with this patch:

opt -S -o /dev/null -globalopt globalopt.ll

results in

opt: ../include/llvm/Support/Casting.h:262: typename cast_retty<X, Y>::ret_type llvm::cast(Y &) [X = llvm::Instruction, Y = llvm::WeakTrackingVH]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.	Program arguments: build-all/bin/opt -S -o /dev/null -globalopt globalopt.ll
 #0 0x0000000002c0c193 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all/bin/opt+0x2c0c193)
 #1 0x0000000002c09e0e llvm::sys::RunSignalHandlers() (build-all/bin/opt+0x2c09e0e)
 #2 0x0000000002c0c516 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007fcf42228630 __restore_rt sigaction.c:0:0
 #4 0x00007fcf3f95b387 raise (/lib64/libc.so.6+0x36387)
 #5 0x00007fcf3f95ca78 abort (/lib64/libc.so.6+0x37a78)
 #6 0x00007fcf3f9541a6 __assert_fail_base (/lib64/libc.so.6+0x2f1a6)
 #7 0x00007fcf3f954252 (/lib64/libc.so.6+0x2f252)
 #8 0x0000000002c9db46 llvm::RecursivelyDeleteTriviallyDeadInstructionsPermissive(llvm::SmallVectorImpl<llvm::WeakTrackingVH>&, llvm::TargetLibraryInfo const*, llvm::MemorySSAUpdater*, std::function<void (llvm::Value*)>) (build-all/bin/opt+0x2c9db46)
 #9 0x00000000024dedb3 CleanupConstantGlobalUsers(llvm::GlobalVariable*, llvm::DataLayout const&) GlobalOpt.cpp:0:0
#10 0x00000000024d98f1 processInternalGlobal(llvm::GlobalVariable*, llvm::GlobalStatus const&, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) GlobalOpt.cpp:0:0
#11 0x00000000024d9257 processGlobal(llvm::GlobalValue&, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) GlobalOpt.cpp:0:0
#12 0x00000000024d7258 optimizeGlobalsInModule(llvm::Module&, llvm::DataLayout const&, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::BlockFrequencyInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) GlobalOpt.cpp:0:0
#13 0x00000000024d57ee llvm::GlobalOptPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x24d57ee)
#14 0x0000000002f0067d llvm::detail::PassModel<llvm::Module, llvm::GlobalOptPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) crtstuff.c:0:0
#15 0x0000000002395088 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x2395088)
#16 0x000000000078d022 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::StringRef>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool) (build-all/bin/opt+0x78d022)
#17 0x000000000079fbad main (build-all/bin/opt+0x79fbad)
#18 0x00007fcf3f947555 __libc_start_main (/lib64/libc.so.6+0x22555)
#19 0x000000000078846c _start (build-all/bin/opt+0x78846c)
Abort

ayrivera added inline comments.
llvm/lib/Transforms/IPO/GlobalOpt.cpp
309

Hi,

I have a small test case that crashes in this line when it tries to create a null value for a x86_mmx load instruction:

test> opt -S -globalopt simple.ll
Cannot create a null constant of that type!  
UNREACHABLE executed at llvm/llvm/lib/IR/Constants.cpp:384!                                                          
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.                                                               
Stack dump:                                                               
0.      Program arguments: opt -S -globalopt simple.ll                    
 #0 0x00000000038d2aed llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) llvm/lib/Support/Unix/Signals.inc:565:0                                                                        
 #1 0x00000000038d2ba4 PrintStackTraceSignalHandler(void*) llvm/lib/Support/Unix/Signals.inc:632:0              
 #2 0x00000000038d0b69 llvm::sys::RunSignalHandlers() llvm/lib/Support/Signals.cpp:96:0                         
 #3 0x00000000038d2531 SignalHandler(int) llvm/lib/Support/Unix/Signals.inc:407:0                               
 #4 0x00007fbeb4870dd0 __restore_rt sigaction.c:0:0                       
 #5 0x00007fbeb336170f raise (/lib64/libc.so.6+0x3770f)                   
 #6 0x00007fbeb334bb25 abort (/lib64/libc.so.6+0x21b25)                   
 #7 0x000000000381316e bindingsErrorHandler(void*, char const*, bool) llvm/lib/Support/ErrorHandling.cpp:218:0  
 #8 0x0000000002ba65ab llvm::Constant::getNullValue(llvm::Type*) llvm/lib/IR/Constants.cpp:384:0                
 #9 0x0000000002f4c4cd CleanupConstantGlobalUsers(llvm::GlobalVariable*, llvm::DataLayout const&) llvm/lib/Transforms/IPO/GlobalOpt.cpp:309:0                                             
#10 0x0000000002f51b41 processInternalGlobal(llvm::GlobalVariable*, llvm::GlobalStatus const&, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) llvm/lib/Transforms/IPO/GlobalOpt.cpp:1556:0     
#11 0x0000000002f520f3 processGlobal(llvm::GlobalValue&, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) llvm/lib/Transforms/IPO/GlobalOpt.cpp:1670:0
#12 0x0000000002f53bf7 OptimizeGlobalVars(llvm::Module&, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>, llvm::SmallPtrSetImpl<llvm::Comdat const*>&) llvm/lib/Transforms/IPO/GlobalOpt.cpp:2065:0
#13 0x0000000002f560e5 optimizeGlobalsInModule(llvm::Module&, llvm::DataLayout const&, llvm::function_ref<llvm::TargetLibraryInfo& (llvm::Function&)>, llvm::function_ref<llvm::TargetTransformInfo& (llvm::Function&)>, llvm::function_ref<llvm::BlockFrequencyInfo& (llvm::Function&)>, llvm::function_ref<llvm::DominatorTree& (llvm::Function&)>) llvm/lib/Transforms/IPO/GlobalOpt.cpp:2639:0
#14 0x0000000002f5632a llvm::GlobalOptPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/lib/Transforms/IPO/GlobalOpt.cpp:2678:0
#15 0x0000000003cd2e24 llvm::detail::PassModel<llvm::Module, llvm::GlobalOptPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/include/llvm/IR/PassManagerInternal.h:89:0
#16 0x0000000002d7811d llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) llvm/include/llvm/IR/PassManager.h:525:0
#17 0x00000000019c0c20 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::StringRef>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool) llvm/tools/opt/NewPMDriver.cpp:487:0
#18 0x00000000019f0e19 main llvm/tools/opt/opt.cpp:818:0
#19 0x00007fbeb334d6a3 __libc_start_main (/lib64/libc.so.6+0x236a3)
#20 0x00000000019ba76e _start (bin/opt+0x19ba76e)
Aborted (core dumped)

It seems that calling getNullValue for a X86_MMX type is not supported. From my understanding, this type doesn't supports LLVM::Constant (https://llvm.org/docs/LangRef.html#x86-mmx-type). I attached a simple test case that reproduce the issue with the following command:

opt -S -globalopt simple.ll

nikic added inline comments.Dec 17 2021, 3:29 AM
llvm/lib/Transforms/IPO/GlobalOpt.cpp
309

Thanks for the report! I submitted D115924 to fix this and related issues.