[llvm] r177331 - Extend global merge pass to optionally consider global constant variables.
Duncan Sands
baldrick at free.fr
Tue Mar 19 12:52:46 PDT 2013
Hi Quentin,
On 18/03/13 23:30, Quentin Colombet wrote:
> Author: qcolombet
> Date: Mon Mar 18 17:30:07 2013
> New Revision: 177331
>
> URL: http://llvm.org/viewvc/llvm-project?rev=177331&view=rev
> Log:
> Extend global merge pass to optionally consider global constant variables.
> Also add some checks to not merge globals used within landing pad instructions or marked as "used".
>
> Modified:
> llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp
> llvm/trunk/test/CodeGen/ARM/global-merge.ll
>
> Modified: llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp?rev=177331&r1=177330&r2=177331&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/GlobalMerge.cpp Mon Mar 18 17:30:07 2013
> @@ -53,6 +53,7 @@
>
> #define DEBUG_TYPE "global-merge"
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> #include "llvm/IR/Attributes.h"
> #include "llvm/IR/Constants.h"
> @@ -60,14 +61,22 @@
> #include "llvm/IR/DerivedTypes.h"
> #include "llvm/IR/Function.h"
> #include "llvm/IR/GlobalVariable.h"
> +#include "llvm/IR/InlineAsm.h"
I guess this include is not needed.
> #include "llvm/IR/Instructions.h"
> #include "llvm/IR/Intrinsics.h"
> +#include "llvm/IR/IntrinsicInst.h"
Is this include needed?
> #include "llvm/IR/Module.h"
> #include "llvm/Pass.h"
> +#include "llvm/Support/CommandLine.h"
> #include "llvm/Target/TargetLowering.h"
> #include "llvm/Target/TargetLoweringObjectFile.h"
> using namespace llvm;
>
> +static cl::opt<bool>
> +EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden,
> + cl::desc("Enable global merge pass on constants"),
> + cl::init(false));
Why is this optional, why not always do it?
> +
> STATISTIC(NumMerged , "Number of globals merged");
> namespace {
> class GlobalMerge : public FunctionPass {
> @@ -78,6 +87,23 @@ namespace {
> bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
> Module &M, bool isConst, unsigned AddrSpace) const;
>
> + /// \brief Check if the given variable has been identified as must keep
> + /// \pre setMustKeepGlobalVariables must have been called on the Module that
> + /// contains GV
> + bool isMustKeepGlobalVariable(const GlobalVariable *GV) const {
> + return MustKeepGlobalVariables.count(GV);
> + }
> +
> + /// Collect every variables marked as "used" or used in a landing pad
> + /// instruction for this Module.
> + void setMustKeepGlobalVariables(Module &M);
> +
> + /// Collect every variables marked as "used"
> + void collectUsedGlobalVariables(Module &M);
> +
> + /// Keep track of the GlobalVariable that are marked as "used"
This comment is misleading since it isn't just for "used" variables. How
about:
/// Keep track of global variables that must not be merged away.
> + SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables;
> +
> public:
> static char ID; // Pass identification, replacement for typeid.
> explicit GlobalMerge(const TargetLowering *tli = 0)
> @@ -169,6 +195,46 @@ bool GlobalMerge::doMerge(SmallVectorImp
> return true;
> }
>
> +void GlobalMerge::collectUsedGlobalVariables(Module &M) {
> + // Extract global variables from llvm.used array
> + const GlobalVariable *GV = M.getGlobalVariable("llvm.used");
> + if (!GV || !GV->hasInitializer()) return;
> +
> + // Should be an array of 'i8*'.
> + const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
> + if (InitList == 0) return;
> +
> + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
> + if (const GlobalVariable *G =
> + dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts()))
> + MustKeepGlobalVariables.insert(G);
> +}
The initial part of the above logic is probably common to every place that
examines llvm.used. Maybe you could factor it out into a shared helper
function?
> +
> +void GlobalMerge::setMustKeepGlobalVariables(Module &M) {
> + // If we already processed a Module, UsedGlobalVariables may have been
> + // populated. Reset the information for this module.
Is the above really possible? I thought a new instance of the pass was created
every time it is run on a module.
> + MustKeepGlobalVariables.clear();
> + collectUsedGlobalVariables(M);
> +
> + for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn;
> + ++IFn) {
> + for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end();
> + IBB != IEndBB; ++IBB) {
> + // Follow the inwoke link to find the landing pad instruction
> + const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator());
> + if (!II) continue;
> +
> + const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst();
> + // Look for globals in the clauses of the landing pad instruction
> + for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses();
> + Idx != NumClauses; ++Idx)
> + if (const GlobalVariable *GV =
> + dyn_cast<GlobalVariable>(LPInst->getClause(Idx)
> + ->stripPointerCasts()))
> + MustKeepGlobalVariables.insert(GV);
> + }
> + }
> +}
>
> bool GlobalMerge::doInitialization(Module &M) {
> DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals,
> @@ -176,6 +242,7 @@ bool GlobalMerge::doInitialization(Modul
> const DataLayout *TD = TLI->getDataLayout();
> unsigned MaxOffset = TLI->getMaximalGlobalOffset();
> bool Changed = false;
> + setMustKeepGlobalVariables(M);
>
> // Grab all non-const globals.
> for (Module::global_iterator I = M.global_begin(),
> @@ -200,6 +267,12 @@ bool GlobalMerge::doInitialization(Modul
> I->getName().startswith(".llvm."))
> continue;
>
> + // Ignore all "required" globals:
> + // - the ones used for EH
> + // - the ones marked with "used" attribute
I think it is a mistake to explain here the logic used to define
MustKeepGlobalVariables. I think it would be better to just say:
// Ignore all "required" globals.
> + if (isMustKeepGlobalVariable(I))
> + continue;
> +
> if (TD->getTypeAllocSize(Ty) < MaxOffset) {
> if (TargetLoweringObjectFile::getKindForGlobal(I, TLI->getTargetMachine())
> .isBSSLocal())
Ciao, Duncan.
More information about the llvm-commits
mailing list