-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CodeGen] Merge lowerConstantIntrinsics into pre-isel lowering #97727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,8 +96,8 @@ static bool replaceConditionalBranchesOnConstant(Instruction *II, | |
return HasDeadBlocks; | ||
} | ||
|
||
static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo &TLI, | ||
DominatorTree *DT) { | ||
bool llvm::lowerConstantIntrinsics(Function &F, const TargetLibraryInfo &TLI, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is still doing an RPOT traversal, although the commit message says that we now avoid the RPOT traversal. Is that intentional? I guess the goal was to call lowerIsConstantIntrisic and lowerObjectSizeCall directly from pre-isel-lowering, rather than running lowerConstantIntrinsics for each such call in the function? I think it is really weird to call this helper multiple times for the same function. Right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes. For most functions, the RPOT is avoided, because they have no constant intrinsics. If a function has constant intrinsics, it still does a RPOT.
This function is called once per function (well, except for the degenerate case you point out below...): here we (somewhat) iterate over the uses, and when we find one, we lower all intrinsic calls in the function. These are then no longer in the use list, the next use is in a different function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, right. So PreISelIntrinsicLowering::lowerIntrinsics is iterating over used intrinsic functions. And then the forEachCall thing is finding out in which functions that the intrinsic is called. That way you avoid doing the RPO scanning for every function in the module. Just a little bit weird that there is a dependency, that the switch in PreISelIntrinsicLowering::lowerIntrinsics for example may trigger on Intrinsic::objectsize, and then the calls to llvm::lowerConstantIntrinsics may lower lots of other instrinsics, and even remove dead code, as a "side-effect". There is no clear correspondance/correlation between what llvm::lowerConstantIntrinsics is doing and what is switched on in PreISelIntrinsicLowering::lowerIntrinsics. |
||
DominatorTree *DT) { | ||
std::optional<DomTreeUpdater> DTU; | ||
if (DT) | ||
DTU.emplace(DT, DomTreeUpdater::UpdateStrategy::Lazy); | ||
|
@@ -165,45 +165,3 @@ LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) { | |
|
||
return PreservedAnalyses::all(); | ||
} | ||
|
||
namespace { | ||
/// Legacy pass for lowering is.constant intrinsics out of the IR. | ||
/// | ||
/// When this pass is run over a function it converts is.constant intrinsics | ||
/// into 'true' or 'false'. This complements the normal constant folding | ||
/// to 'true' as part of Instruction Simplify passes. | ||
class LowerConstantIntrinsics : public FunctionPass { | ||
public: | ||
static char ID; | ||
LowerConstantIntrinsics() : FunctionPass(ID) { | ||
initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
bool runOnFunction(Function &F) override { | ||
const TargetLibraryInfo &TLI = | ||
getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); | ||
DominatorTree *DT = nullptr; | ||
if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) | ||
DT = &DTWP->getDomTree(); | ||
return lowerConstantIntrinsics(F, TLI, DT); | ||
} | ||
|
||
void getAnalysisUsage(AnalysisUsage &AU) const override { | ||
AU.addRequired<TargetLibraryInfoWrapperPass>(); | ||
AU.addPreserved<GlobalsAAWrapperPass>(); | ||
AU.addPreserved<DominatorTreeWrapperPass>(); | ||
} | ||
}; | ||
} // namespace | ||
|
||
char LowerConstantIntrinsics::ID = 0; | ||
INITIALIZE_PASS_BEGIN(LowerConstantIntrinsics, "lower-constant-intrinsics", | ||
"Lower constant intrinsics", false, false) | ||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | ||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) | ||
INITIALIZE_PASS_END(LowerConstantIntrinsics, "lower-constant-intrinsics", | ||
"Lower constant intrinsics", false, false) | ||
|
||
FunctionPass *llvm::createLowerConstantIntrinsicsPass() { | ||
return new LowerConstantIntrinsics(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assert fails for input like this
since lowerConstantIntrinsics is doing an RPOT traversal to find out which intrinsics to lower. So it may fail to find CI, and then there is no changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Opened #102442 to remove the assertion and add a test case.