[llvm-branch-commits] [llvm] Add SimplifyTypeTests pass. (PR #141327)
Florian Mayer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed May 28 10:18:10 PDT 2025
================
@@ -2478,3 +2479,76 @@ 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 MaySimplifyPtr = [&](Value *Ptr) {
+ 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);
+ };
+ auto MaySimplifyInt = [&](Value *Op) {
+ auto *PtrAsInt = dyn_cast<ConstantExpr>(Op);
+ if (!PtrAsInt || PtrAsInt->getOpcode() != Instruction::PtrToInt)
+ return false;
+ return MaySimplifyPtr(PtrAsInt->getOperand(0));
+ };
+ for (User *U : make_early_inc_range(GV.users())) {
+ if (auto *CI = dyn_cast<ICmpInst>(U)) {
+ if (CI->getPredicate() == CmpInst::ICMP_EQ &&
+ MaySimplifyPtr(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;
+ }
+ }
+ 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 &&
+ MaySimplifyInt(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 &&
+ MaySimplifyInt(CI->getOperand(0))) {
+ // This is an equality comparison. Unlike in the case above it
+ // remained as an integer compare.
+ CI->replaceAllUsesWith(ConstantInt::getTrue(M.getContext()));
+ CI->eraseFromParent();
+ Changed = true;
+ }
+ }
+ }
+ }
+
+ if (!Changed)
+ return PreservedAnalyses::all();
+ return PreservedAnalyses::none();
----------------
fmayer wrote:
Is that true? E.g. the CFG doesn't change, right? Could we do what we do in HWASan: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp#L485?
https://github.com/llvm/llvm-project/pull/141327
More information about the llvm-branch-commits
mailing list