-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Add SimplifyTypeTests pass. #141327
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
base: users/pcc/spr/main.add-simplifytypetests-pass
Are you sure you want to change the base?
Add SimplifyTypeTests pass. #141327
Conversation
Created using spr 1.3.6-beta.1
@llvm/pr-subscribers-llvm-transforms Author: Peter Collingbourne (pcc) ChangesThis pass figures out whether inlining has exposed a constant address to TODO: Add tests. Full diff: https://github.com/llvm/llvm-project/pull/141327.diff 4 Files Affected:
diff --git a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
index 02adcd8bfd45d..40f2d2c4fadf7 100644
--- a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
+++ b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h
@@ -223,6 +223,11 @@ class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> {
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
+class SimplifyTypeTestsPass : public PassInfoMixin<SimplifyTypeTestsPass> {
+public:
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
+
} // end namespace llvm
#endif // LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index f3654600c5abb..e3adceed7d70a 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1464,6 +1464,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
if (!LTOPreLink)
MPM.addPass(EliminateAvailableExternallyPass());
+ MPM.addPass(SimplifyTypeTestsPass());
+
// Do RPO function attribute inference across the module to forward-propagate
// attributes where applicable.
// FIXME: Is this really an optimization rather than a canonicalization?
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 94dabe290213d..35ad73738d71d 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -100,6 +100,7 @@ MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass())
MODULE_PASS("lower-emutls", LowerEmuTLSPass())
MODULE_PASS("lower-global-dtors", LowerGlobalDtorsPass())
MODULE_PASS("lower-ifunc", LowerIFuncPass())
+MODULE_PASS("simplify-type-tests", SimplifyTypeTestsPass())
MODULE_PASS("lowertypetests", LowerTypeTestsPass())
MODULE_PASS("fatlto-cleanup", FatLtoCleanup())
MODULE_PASS("pgo-force-function-attrs", PGOForceFunctionAttrsPass(PGOOpt ? PGOOpt->ColdOptType : PGOOptions::ColdFuncOpt::Default))
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index 428c4641a7f56..344ac9f5a8f95 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -2456,3 +2456,64 @@ PreservedAnalyses LowerTypeTestsPass::run(Module &M,
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
+
+PreservedAnalyses SimplifyTypeTestsPass::run(Module &M,
+ ModuleAnalysisManager &AM) {
+ bool Changed = false;
+ // Figure out whether inlining has exposed a constant address to a lowered
+ // type test, and remove the test if so and the address is known to pass the
+ // test. Unfortunately this pass ends up needing to reverse engineer what
+ // LowerTypeTests did; this is currently inherent to the design of ThinLTO
+ // importing where LowerTypeTests needs to run at the start.
+ for (auto &GV : M.globals()) {
+ if (!GV.getName().starts_with("__typeid_") ||
+ !GV.getName().ends_with("_global_addr"))
+ continue;
+ auto *MD = MDString::get(M.getContext(),
+ GV.getName().substr(9, GV.getName().size() - 21));
+ auto MaySimplify = [&](Value *Op) {
+ auto *PtrAsInt = dyn_cast<ConstantExpr>(Op);
+ if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
+ return false;
+ auto *Ptr = PtrAsInt->getOperand(0);
+ if (auto *GV = dyn_cast<GlobalValue>(Ptr))
+ if (auto *CFIGV = M.getNamedValue((GV->getName() + ".cfi").str()))
+ Ptr = CFIGV;
+ return isKnownTypeIdMember(MD, M.getDataLayout(), Ptr, 0);
+ };
+ for (User *U : GV.users()) {
+ auto *CE = dyn_cast<ConstantExpr>(U);
+ if (!CE || CE->getOpcode() != Instruction::PtrToInt)
+ continue;
+ for (Use &U : make_early_inc_range(CE->uses())) {
+ auto *CE = dyn_cast<ConstantExpr>(U.getUser());
+ if (U.getOperandNo() == 1 && CE &&
+ CE->getOpcode() == Instruction::Sub &&
+ MaySimplify(CE->getOperand(0))) {
+ // This is a computation of PtrOffset as generated by
+ // LowerTypeTestsModule::lowerTypeTestCall above. If
+ // isKnownTypeIdMember passes we just pretend it evaluated to 0. This
+ // should cause later passes to remove the range and alignment checks.
+ // The bitset checks won't be removed but those are uncommon.
+ CE->replaceAllUsesWith(ConstantInt::get(CE->getType(), 0));
+ Changed = true;
+ }
+ auto *CI = dyn_cast<ICmpInst>(U.getUser());
+ if (U.getOperandNo() == 1 && CI &&
+ CI->getPredicate() == CmpInst::ICMP_EQ &&
+ MaySimplify(CI->getOperand(0))) {
+ // This is an equality comparison (TypeTestResolution::Single case in
+ // lowerTypeTestCall). In this case we just replace the comparison
+ // with true.
+ CI->replaceAllUsesWith(ConstantInt::getTrue(M.getContext()));
+ CI->eraseFromParent();
+ Changed = true;
+ }
+ }
+ }
+ }
+
+ if (!Changed)
+ return PreservedAnalyses::all();
+ return PreservedAnalyses::none();
+}
|
Created using spr 1.3.6-beta.1
✅ With the latest revision this PR passed the C/C++ code formatter. |
This pass figures out whether inlining has exposed a constant address to
a lowered type test, and remove the test if so and the address is known
to pass the test. Unfortunately this pass ends up needing to reverse
engineer what LowerTypeTests did; this is currently inherent to the design
of ThinLTO importing where LowerTypeTests needs to run at the start.