2012-10-16 10:21:30 +08:00
|
|
|
//===-- IPO.cpp -----------------------------------------------------------===//
|
2009-03-07 00:52:18 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2015-10-31 07:02:38 +08:00
|
|
|
// This file implements the common infrastructure (including C bindings) for
|
|
|
|
// libLLVMIPO.a, which implements several transformations over the LLVM
|
2010-10-08 02:09:59 +08:00
|
|
|
// intermediate representation.
|
2009-03-07 00:52:18 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm-c/Transforms/IPO.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm-c/Initialization.h"
|
2015-02-13 18:01:29 +08:00
|
|
|
#include "llvm/IR/LegacyPassManager.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/InitializePasses.h"
|
2009-03-07 00:52:18 +08:00
|
|
|
#include "llvm/Transforms/IPO.h"
|
[PM] Port the always inliner to the new pass manager in a much more
minimal and boring form than the old pass manager's version.
This pass does the very minimal amount of work necessary to inline
functions declared as always-inline. It doesn't support a wide array of
things that the legacy pass manager did support, but is alse ... about
20 lines of code. So it has that going for it. Notably things this
doesn't support:
- Array alloca merging
- To support the above, bottom-up inlining with careful history
tracking and call graph updates
- DCE of the functions that become dead after this inlining.
- Inlining through call instructions with the always_inline attribute.
Instead, it focuses on inlining functions with that attribute.
The first I've omitted because I'm hoping to just turn it off for the
primary pass manager. If that doesn't pan out, I can add it here but it
will be reasonably expensive to do so.
The second should really be handled by running global-dce after the
inliner. I don't want to re-implement the non-trivial logic necessary to
do comdat-correct DCE of functions. This means the -O0 pipeline will
have to be at least 'always-inline,global-dce', but that seems
reasonable to me. If others are seriously worried about this I'd like to
hear about it and understand why. Again, this is all solveable by
factoring that logic into a utility and calling it here, but I'd like to
wait to do that until there is a clear reason why the existing
pass-based factoring won't work.
The final point is a serious one. I can fairly easily add support for
this, but it seems both costly and a confusing construct for the use
case of the always inliner running at -O0. This attribute can of course
still impact the normal inliner easily (although I find that
a questionable re-use of the same attribute). I've started a discussion
to sort out what semantics we want here and based on that can figure out
if it makes sense ta have this complexity at O0 or not.
One other advantage of this design is that it should be quite a bit
faster due to checking for whether the function is a viable candidate
for inlining exactly once per function instead of doing it for each call
site.
Anyways, hopefully a reasonable starting point for this pass.
Differential Revision: https://reviews.llvm.org/D23299
llvm-svn: 278896
2016-08-17 10:56:20 +08:00
|
|
|
#include "llvm/Transforms/IPO/AlwaysInliner.h"
|
2016-02-18 19:03:11 +08:00
|
|
|
#include "llvm/Transforms/IPO/FunctionAttrs.h"
|
2009-03-07 00:52:18 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2010-10-08 02:09:59 +08:00
|
|
|
void llvm::initializeIPO(PassRegistry &Registry) {
|
|
|
|
initializeArgPromotionPass(Registry);
|
2017-10-25 21:40:08 +08:00
|
|
|
initializeCalledValuePropagationLegacyPassPass(Registry);
|
2016-05-05 08:51:09 +08:00
|
|
|
initializeConstantMergeLegacyPassPass(Registry);
|
2015-12-16 07:00:08 +08:00
|
|
|
initializeCrossDSOCFIPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeDAEPass(Registry);
|
|
|
|
initializeDAHPass(Registry);
|
2015-12-27 16:13:45 +08:00
|
|
|
initializeForceFunctionAttrsLegacyPassPass(Registry);
|
2016-05-04 03:39:15 +08:00
|
|
|
initializeGlobalDCELegacyPassPass(Registry);
|
2016-04-26 08:28:01 +08:00
|
|
|
initializeGlobalOptLegacyPassPass(Registry);
|
2016-11-17 07:40:26 +08:00
|
|
|
initializeGlobalSplitPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeIPCPPass(Registry);
|
[PM] Port the always inliner to the new pass manager in a much more
minimal and boring form than the old pass manager's version.
This pass does the very minimal amount of work necessary to inline
functions declared as always-inline. It doesn't support a wide array of
things that the legacy pass manager did support, but is alse ... about
20 lines of code. So it has that going for it. Notably things this
doesn't support:
- Array alloca merging
- To support the above, bottom-up inlining with careful history
tracking and call graph updates
- DCE of the functions that become dead after this inlining.
- Inlining through call instructions with the always_inline attribute.
Instead, it focuses on inlining functions with that attribute.
The first I've omitted because I'm hoping to just turn it off for the
primary pass manager. If that doesn't pan out, I can add it here but it
will be reasonably expensive to do so.
The second should really be handled by running global-dce after the
inliner. I don't want to re-implement the non-trivial logic necessary to
do comdat-correct DCE of functions. This means the -O0 pipeline will
have to be at least 'always-inline,global-dce', but that seems
reasonable to me. If others are seriously worried about this I'd like to
hear about it and understand why. Again, this is all solveable by
factoring that logic into a utility and calling it here, but I'd like to
wait to do that until there is a clear reason why the existing
pass-based factoring won't work.
The final point is a serious one. I can fairly easily add support for
this, but it seems both costly and a confusing construct for the use
case of the always inliner running at -O0. This attribute can of course
still impact the normal inliner easily (although I find that
a questionable re-use of the same attribute). I've started a discussion
to sort out what semantics we want here and based on that can figure out
if it makes sense ta have this complexity at O0 or not.
One other advantage of this design is that it should be quite a bit
faster due to checking for whether the function is a viable candidate
for inlining exactly once per function instead of doing it for each call
site.
Anyways, hopefully a reasonable starting point for this pass.
Differential Revision: https://reviews.llvm.org/D23299
llvm-svn: 278896
2016-08-17 10:56:20 +08:00
|
|
|
initializeAlwaysInlinerLegacyPassPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeSimpleInlinerPass(Registry);
|
2015-12-27 16:41:34 +08:00
|
|
|
initializeInferFunctionAttrsLegacyPassPass(Registry);
|
2016-04-27 04:15:52 +08:00
|
|
|
initializeInternalizeLegacyPassPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeLoopExtractorPass(Registry);
|
2018-01-24 05:51:34 +08:00
|
|
|
initializeBlockExtractorPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeSingleLoopExtractorPass(Registry);
|
IR: New representation for CFI and virtual call optimization pass metadata.
The bitset metadata currently used in LLVM has a few problems:
1. It has the wrong name. The name "bitset" refers to an implementation
detail of one use of the metadata (i.e. its original use case, CFI).
This makes it harder to understand, as the name makes no sense in the
context of virtual call optimization.
2. It is represented using a global named metadata node, rather than
being directly associated with a global. This makes it harder to
manipulate the metadata when rebuilding global variables, summarise it
as part of ThinLTO and drop unused metadata when associated globals are
dropped. For this reason, CFI does not currently work correctly when
both CFI and vcall opt are enabled, as vcall opt needs to rebuild vtable
globals, and fails to associate metadata with the rebuilt globals. As I
understand it, the same problem could also affect ASan, which rebuilds
globals with a red zone.
This patch solves both of those problems in the following way:
1. Rename the metadata to "type metadata". This new name reflects how
the metadata is currently being used (i.e. to represent type information
for CFI and vtable opt). The new name is reflected in the name for the
associated intrinsic (llvm.type.test) and pass (LowerTypeTests).
2. Attach metadata directly to the globals that it pertains to, rather
than using the "llvm.bitsets" global metadata node as we are doing now.
This is done using the newly introduced capability to attach
metadata to global variables (r271348 and r271358).
See also: http://lists.llvm.org/pipermail/llvm-dev/2016-June/100462.html
Differential Revision: http://reviews.llvm.org/D21053
llvm-svn: 273729
2016-06-25 05:21:32 +08:00
|
|
|
initializeLowerTypeTestsPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeMergeFunctionsPass(Registry);
|
2016-06-28 00:50:18 +08:00
|
|
|
initializePartialInlinerLegacyPassPass(Registry);
|
2016-02-18 19:03:11 +08:00
|
|
|
initializePostOrderFunctionAttrsLegacyPassPass(Registry);
|
[PM] Port ReversePostOrderFunctionAttrs to the new PM
Below are my super rough notes when porting. They can probably serve as
a basic guide for porting other passes to the new PM. As I port more
passes I'll expand and generalize this and make a proper
docs/HowToPortToNewPassManager.rst document. There is also missing
documentation for general concepts and API's in the new PM which will
require some documentation.
Once there is proper documentation in place we can put up a list of
passes that have to be ported and game-ify/crowdsource the rest of the
porting (at least of the middle end; the backend is still unclear).
I will however be taking personal responsibility for ensuring that the
LLD/ELF LTO pipeline is ported in a timely fashion. The remaining passes
to be ported are (do something like
`git grep "<the string in the bullet point below>"` to find the pass):
General Scalar:
[ ] Simplify the CFG
[ ] Jump Threading
[ ] MemCpy Optimization
[ ] Promote Memory to Register
[ ] MergedLoadStoreMotion
[ ] Lazy Value Information Analysis
General IPO:
[ ] Dead Argument Elimination
[ ] Deduce function attributes in RPO
Loop stuff / vectorization stuff:
[ ] Alignment from assumptions
[ ] Canonicalize natural loops
[ ] Delete dead loops
[ ] Loop Access Analysis
[ ] Loop Invariant Code Motion
[ ] Loop Vectorization
[ ] SLP Vectorizer
[ ] Unroll loops
Devirtualization / CFI:
[ ] Cross-DSO CFI
[ ] Whole program devirtualization
[ ] Lower bitset metadata
CGSCC passes:
[ ] Function Integration/Inlining
[ ] Remove unused exception handling info
[ ] Promote 'by reference' arguments to scalars
Please let me know if you are interested in working on any of the passes
in the above list (e.g. reply to the post-commit thread for this patch).
I'll probably be tackling "General Scalar" and "General IPO" first FWIW.
Steps as I port "Deduce function attributes in RPO"
---------------------------------------------------
(note: if you are doing any work based on these notes, please leave a
note in the post-commit review thread for this commit with any
improvements / suggestions / incompleteness you ran into!)
Note: "Deduce function attributes in RPO" is a module pass.
1. Do preparatory refactoring.
Do preparatory factoring. In this case all I had to do was to pull out a static helper (r272503).
(TODO: give more advice here e.g. if pass holds state or something)
2. Rename the old pass class.
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
Rename class ReversePostOrderFunctionAttrs -> ReversePostOrderFunctionAttrsLegacyPass
in preparation for adding a class ReversePostOrderFunctionAttrs as the pass in the new PM.
(edit: actually wait what? The new class name will be
ReversePostOrderFunctionAttrsPass, so it doesn't conflict. So this step is
sort of useless churn).
llvm/include/llvm/InitializePasses.h
llvm/lib/LTO/LTOCodeGenerator.cpp
llvm/lib/Transforms/IPO/IPO.cpp
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
Rename initializeReversePostOrderFunctionAttrsPass -> initializeReversePostOrderFunctionAttrsLegacyPassPass
(note that the "PassPass" thing falls out of `s/ReversePostOrderFunctionAttrs/ReversePostOrderFunctionAttrsLegacyPass/`)
Note that the INITIALIZE_PASS macro is what creates this identifier name, so renaming the class requires this renaming too.
Note that createReversePostOrderFunctionAttrsPass does not need to be
renamed since its name is not generated from the class name.
3. Add the new PM pass class.
In the new PM all passes need to have their
declaration in a header somewhere, so you will often need to add a header.
In this case
llvm/include/llvm/Transforms/IPO/FunctionAttrs.h is already there because
PostOrderFunctionAttrsPass was already ported.
The file-level comment from the .cpp file can be used as the file-level
comment for the new header. You may want to tweak the wording slightly
from "this file implements" to "this file provides" or similar.
Add declaration for the new PM pass in this header:
class ReversePostOrderFunctionAttrsPass
: public PassInfoMixin<ReversePostOrderFunctionAttrsPass> {
public:
PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
};
Its name should end with `Pass` for consistency (note that this doesn't
collide with the names of most old PM passes). E.g. call it
`<name of the old PM pass>Pass`.
Also, move the doxygen comment from the old PM pass to the declaration of
this class in the header.
Also, include the declaration for the new PM class
`llvm/Transforms/IPO/FunctionAttrs.h` at the top of the file (in this case,
it was already done when the other pass in this file was ported).
Now define the `run` method for the new class.
The main things here are:
a) Use AM.getResult<...>(M) to get results instead of `getAnalysis<...>()`
b) If the old PM pass would have returned "false" (i.e. `Changed ==
false`), then you should return PreservedAnalyses::all();
c) In the old PM getAnalysisUsage method, observe the calls
`AU.addPreserved<...>();`.
In the case `Changed == true`, for each preserved analysis you should do
call `PA.preserve<...>()` on a PreservedAnalyses object and return it.
E.g.:
PreservedAnalyses PA;
PA.preserve<CallGraphAnalysis>();
return PA;
Note that calls to skipModule/skipFunction are not supported in the new PM
currently, so optnone and optimization bisect support do not work. You can
just drop those calls for now.
4. Add the pass to the new PM pass registry to make it available in opt.
In llvm/lib/Passes/PassBuilder.cpp add a #include for your header.
`#include "llvm/Transforms/IPO/FunctionAttrs.h"`
In this case there is already an include (from when
PostOrderFunctionAttrsPass was ported).
Add your pass to llvm/lib/Passes/PassRegistry.def
In this case, I added
`MODULE_PASS("rpo-functionattrs", ReversePostOrderFunctionAttrsPass())`
The string is from the `INITIALIZE_PASS*` macros used in the old pass
manager.
Then choose a test that uses the pass and use the new PM `-passes=...` to
run it.
E.g. in this case there is a test that does:
; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s
I have added the line:
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<targetlibinfo>,cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s
The `-aa-pipeline=basic-aa` and
`require<targetlibinfo>,cgscc(function-attrs)` are what is needed to run
functionattrs in the new PM (note that in the new PM "functionattrs"
becomes "function-attrs" for some reason). This is just pulled from
`readattrs.ll` which contains the change from when functionattrs was ported
to the new PM.
Adding rpo-functionattrs causes the pass that was just ported to run.
llvm-svn: 272505
2016-06-12 15:48:51 +08:00
|
|
|
initializeReversePostOrderFunctionAttrsLegacyPassPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializePruneEHPass(Registry);
|
2018-03-23 06:07:53 +08:00
|
|
|
initializeIPSCCPLegacyPassPass(Registry);
|
2015-10-31 07:28:12 +08:00
|
|
|
initializeStripDeadPrototypesLegacyPassPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
initializeStripSymbolsPass(Registry);
|
|
|
|
initializeStripDebugDeclarePass(Registry);
|
|
|
|
initializeStripDeadDebugInfoPass(Registry);
|
|
|
|
initializeStripNonDebugSymbolsPass(Registry);
|
2013-12-13 04:45:08 +08:00
|
|
|
initializeBarrierNoopPass(Registry);
|
2016-05-05 10:37:32 +08:00
|
|
|
initializeEliminateAvailableExternallyLegacyPassPass(Registry);
|
2016-05-28 06:30:44 +08:00
|
|
|
initializeSampleProfileLoaderLegacyPassPass(Registry);
|
2016-07-19 05:22:24 +08:00
|
|
|
initializeFunctionImportLegacyPassPass(Registry);
|
2016-02-10 06:50:34 +08:00
|
|
|
initializeWholeProgramDevirtPass(Registry);
|
2010-10-08 02:09:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMInitializeIPO(LLVMPassRegistryRef R) {
|
|
|
|
initializeIPO(*unwrap(R));
|
|
|
|
}
|
|
|
|
|
2009-03-07 00:52:18 +08:00
|
|
|
void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createArgumentPromotionPass());
|
|
|
|
}
|
|
|
|
|
2017-10-25 21:40:08 +08:00
|
|
|
void LLVMAddCalledValuePropagationPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createCalledValuePropagationPass());
|
|
|
|
}
|
|
|
|
|
2009-03-07 00:52:18 +08:00
|
|
|
void LLVMAddConstantMergePass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createConstantMergePass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createDeadArgEliminationPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
|
2016-02-18 19:03:11 +08:00
|
|
|
unwrap(PM)->add(createPostOrderFunctionAttrsLegacyPass());
|
2009-03-07 00:52:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createFunctionInliningPass());
|
|
|
|
}
|
|
|
|
|
2011-07-26 23:23:23 +08:00
|
|
|
void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM) {
|
[PM] Port the always inliner to the new pass manager in a much more
minimal and boring form than the old pass manager's version.
This pass does the very minimal amount of work necessary to inline
functions declared as always-inline. It doesn't support a wide array of
things that the legacy pass manager did support, but is alse ... about
20 lines of code. So it has that going for it. Notably things this
doesn't support:
- Array alloca merging
- To support the above, bottom-up inlining with careful history
tracking and call graph updates
- DCE of the functions that become dead after this inlining.
- Inlining through call instructions with the always_inline attribute.
Instead, it focuses on inlining functions with that attribute.
The first I've omitted because I'm hoping to just turn it off for the
primary pass manager. If that doesn't pan out, I can add it here but it
will be reasonably expensive to do so.
The second should really be handled by running global-dce after the
inliner. I don't want to re-implement the non-trivial logic necessary to
do comdat-correct DCE of functions. This means the -O0 pipeline will
have to be at least 'always-inline,global-dce', but that seems
reasonable to me. If others are seriously worried about this I'd like to
hear about it and understand why. Again, this is all solveable by
factoring that logic into a utility and calling it here, but I'd like to
wait to do that until there is a clear reason why the existing
pass-based factoring won't work.
The final point is a serious one. I can fairly easily add support for
this, but it seems both costly and a confusing construct for the use
case of the always inliner running at -O0. This attribute can of course
still impact the normal inliner easily (although I find that
a questionable re-use of the same attribute). I've started a discussion
to sort out what semantics we want here and based on that can figure out
if it makes sense ta have this complexity at O0 or not.
One other advantage of this design is that it should be quite a bit
faster due to checking for whether the function is a viable candidate
for inlining exactly once per function instead of doing it for each call
site.
Anyways, hopefully a reasonable starting point for this pass.
Differential Revision: https://reviews.llvm.org/D23299
llvm-svn: 278896
2016-08-17 10:56:20 +08:00
|
|
|
unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass());
|
2011-07-26 23:23:23 +08:00
|
|
|
}
|
|
|
|
|
2009-03-07 00:52:18 +08:00
|
|
|
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createGlobalDCEPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createGlobalOptimizerPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createIPConstantPropagationPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddPruneEHPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createPruneEHPass());
|
|
|
|
}
|
|
|
|
|
2010-04-10 04:43:20 +08:00
|
|
|
void LLVMAddIPSCCPPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createIPSCCPPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddInternalizePass(LLVMPassManagerRef PM, unsigned AllButMain) {
|
2016-04-13 12:20:32 +08:00
|
|
|
auto PreserveMain = [=](const GlobalValue &GV) {
|
|
|
|
return AllButMain && GV.getName() == "main";
|
|
|
|
};
|
|
|
|
unwrap(PM)->add(createInternalizePass(PreserveMain));
|
2010-04-10 04:43:20 +08:00
|
|
|
}
|
|
|
|
|
2009-03-07 00:52:18 +08:00
|
|
|
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createStripDeadPrototypesPass());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM) {
|
|
|
|
unwrap(PM)->add(createStripSymbolsPass());
|
|
|
|
}
|