From ef6f211cdaa883525956cd433548347be1dbe3a6 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 4 Jun 2025 19:11:08 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20change?= =?UTF-8?q?s=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 [skip ci] --- .../llvm/Transforms/IPO/LowerTypeTests.h | 5 + llvm/lib/Passes/PassBuilderPipelines.cpp | 3 + llvm/lib/Passes/PassRegistry.def | 1 + llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 102 +++++++++++++++++- .../Other/new-pm-thinlto-postlink-defaults.ll | 1 + .../new-pm-thinlto-postlink-pgo-defaults.ll | 1 + ...-pm-thinlto-postlink-samplepgo-defaults.ll | 1 + llvm/test/ThinLTO/X86/cfi-devirt.ll | 2 +- .../LowerTypeTests/export-allones.ll | 4 +- .../LowerTypeTests/export-bytearray.ll | 4 +- .../Transforms/LowerTypeTests/export-icall.ll | 2 +- llvm/test/Transforms/LowerTypeTests/import.ll | 58 +++++----- .../Transforms/LowerTypeTests/simplify.ll | 13 ++- .../Transforms/SimplifyTypeTests/basic.ll | 46 ++++++++ 14 files changed, 193 insertions(+), 50 deletions(-) create mode 100644 llvm/test/Transforms/SimplifyTypeTests/basic.ll 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 { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; +class SimplifyTypeTestsPass : public PassInfoMixin { +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..70b4eb68ffa2f 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1288,6 +1288,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // and argument promotion. MPM.addPass(DeadArgumentEliminationPass()); + if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink) + MPM.addPass(SimplifyTypeTestsPass()); + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink) MPM.addPass(CoroCleanupPass()); diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index e2824475ce8c3..8cddb70800fb9 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -101,6 +101,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 de9efc5b25b4b..edddc52fa950f 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -19,11 +19,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeMetadataUtils.h" #include "llvm/Analysis/ValueTracking.h" @@ -779,9 +782,8 @@ Value *LowerTypeTestsModule::lowerTypeTestCall(Metadata *TypeId, CallInst *CI, // result, causing the comparison to fail if they are nonzero. The rotate // also conveniently gives us a bit offset to use during the load from // the bitset. - Value *BitOffset = B.CreateIntrinsic( - IntPtrTy, Intrinsic::fshr, - {PtrOffset, PtrOffset, B.CreateZExt(TIL.AlignLog2, IntPtrTy)}); + Value *BitOffset = B.CreateIntrinsic(IntPtrTy, Intrinsic::fshr, + {PtrOffset, PtrOffset, TIL.AlignLog2}); Value *OffsetInRange = B.CreateICmpULE(BitOffset, TIL.SizeM1); @@ -1033,7 +1035,7 @@ LowerTypeTestsModule::importTypeId(StringRef TypeId) { if (TIL.TheKind == TypeTestResolution::ByteArray || TIL.TheKind == TypeTestResolution::Inline || TIL.TheKind == TypeTestResolution::AllOnes) { - TIL.AlignLog2 = ImportConstant("align", TTRes.AlignLog2, 8, Int8Ty); + TIL.AlignLog2 = ImportConstant("align", TTRes.AlignLog2, 8, IntPtrTy); TIL.SizeM1 = ImportConstant("size_m1", TTRes.SizeM1, TTRes.SizeM1BitWidth, IntPtrTy); } @@ -1154,7 +1156,7 @@ void LowerTypeTestsModule::lowerTypeTestCalls( TypeIdLowering TIL; TIL.OffsetedGlobal = ConstantExpr::getGetElementPtr( Int8Ty, CombinedGlobalAddr, ConstantInt::get(IntPtrTy, BSI.ByteOffset)), - TIL.AlignLog2 = ConstantInt::get(Int8Ty, BSI.AlignLog2); + TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.AlignLog2); TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.BitSize - 1); if (BSI.isAllOnes()) { TIL.TheKind = (BSI.BitSize == 1) ? TypeTestResolution::Single @@ -2472,3 +2474,93 @@ 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. + // + // We look for things like: + // + // sub (i64 ptrtoint (ptr @_Z2fpv to i64), i64 ptrtoint (ptr @__typeid__ZTSFvvE_global_addr to i64)) + // + // which gets replaced with 0 if _Z2fpv (more specifically _Z2fpv.cfi, the + // function referred to by the jump table) is a member of the type _ZTSFvv, as + // well as things like + // + // icmp eq ptr @_Z2fpv, @__typeid__ZTSFvvE_global_addr + // + // which gets replaced with true if _Z2fpv is a member. + for (auto &GV : M.globals()) { + if (!GV.getName().starts_with("__typeid_") || + !GV.getName().ends_with("_global_addr")) + continue; + // __typeid_foo_global_addr -> foo + auto *MD = MDString::get(M.getContext(), + GV.getName().substr(9, GV.getName().size() - 21)); + auto MaySimplifyPtr = [&](Value *Ptr) { + if (auto *GV = dyn_cast(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(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(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(U); + if (!CE || CE->getOpcode() != Instruction::PtrToInt) + continue; + for (Use &U : make_early_inc_range(CE->uses())) { + auto *CE = dyn_cast(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(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(); + PreservedAnalyses PA = PreservedAnalyses::none(); + PA.preserve(); + PA.preserve(); + PA.preserve(); + return PA; +} diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll index ed13402e1c4b1..62bb02d9b3c40 100644 --- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll @@ -159,6 +159,7 @@ ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass +; CHECK-O-NEXT: Running pass: SimplifyTypeTestsPass ; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-POSTLINK-O-NEXT: Running pass: GlobalOptPass ; CHECK-POSTLINK-O-NEXT: Running pass: GlobalDCEPass diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll index c82c34f7ff01e..0da7a9f73bdce 100644 --- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll @@ -143,6 +143,7 @@ ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass +; CHECK-O-NEXT: Running pass: SimplifyTypeTestsPass ; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-O-NEXT: Running pass: GlobalOptPass ; CHECK-O-NEXT: Running pass: GlobalDCEPass diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll index d375747547d61..38b7890682783 100644 --- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll @@ -152,6 +152,7 @@ ; CHECK-O-NEXT: Invalidating analysis: ShouldNotRunFunctionPassesAnalysis ; CHECK-O-NEXT: Invalidating analysis: InlineAdvisorAnalysis ; CHECK-O-NEXT: Running pass: DeadArgumentEliminationPass +; CHECK-O-NEXT: Running pass: SimplifyTypeTestsPass ; CHECK-O-NEXT: Running pass: CoroCleanupPass ; CHECK-O-NEXT: Running pass: GlobalOptPass ; CHECK-O-NEXT: Running pass: GlobalDCEPass diff --git a/llvm/test/ThinLTO/X86/cfi-devirt.ll b/llvm/test/ThinLTO/X86/cfi-devirt.ll index 0a9935b036b5a..c1d0b5fee8cc8 100644 --- a/llvm/test/ThinLTO/X86/cfi-devirt.ll +++ b/llvm/test/ThinLTO/X86/cfi-devirt.ll @@ -91,7 +91,7 @@ cont2: ; CHECK-IR: br i1 {{.*}}, label %trap, label %cont2 ; We still have to call it as virtual. - ; CHECK-IR: %call3 = tail call i32 %4 + ; CHECK-IR: %call3 = tail call i32 % %call3 = tail call i32 %5(ptr nonnull %obj, i32 %call) ret i32 %call3 } diff --git a/llvm/test/Transforms/LowerTypeTests/export-allones.ll b/llvm/test/Transforms/LowerTypeTests/export-allones.ll index 9708f4d761920..908c9320b039a 100644 --- a/llvm/test/Transforms/LowerTypeTests/export-allones.ll +++ b/llvm/test/Transforms/LowerTypeTests/export-allones.ll @@ -142,11 +142,11 @@ ; CHECK: [[G:@[0-9]+]] = private constant { [2048 x i8] } zeroinitializer ; CHECK: @__typeid_typeid1_global_addr = hidden alias i8, ptr [[G]] -; X86: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 1 to ptr) +; X86: @__typeid_typeid1_align = hidden alias i8, inttoptr (i64 1 to ptr) ; X86: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 1 to ptr) ; CHECK: @__typeid_typeid2_global_addr = hidden alias i8, getelementptr (i8, ptr [[G]], i64 4) -; X86: @__typeid_typeid2_align = hidden alias i8, inttoptr (i8 2 to ptr) +; X86: @__typeid_typeid2_align = hidden alias i8, inttoptr (i64 2 to ptr) ; X86: @__typeid_typeid2_size_m1 = hidden alias i8, inttoptr (i64 128 to ptr) ; ARM-NOT: alias {{.*}} inttoptr diff --git a/llvm/test/Transforms/LowerTypeTests/export-bytearray.ll b/llvm/test/Transforms/LowerTypeTests/export-bytearray.ll index fef93d016267e..0ef9f584f767c 100644 --- a/llvm/test/Transforms/LowerTypeTests/export-bytearray.ll +++ b/llvm/test/Transforms/LowerTypeTests/export-bytearray.ll @@ -15,13 +15,13 @@ ; CHECK: [[B:@[0-9]+]] = private constant [258 x i8] c"\03\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01" ; CHECK: @__typeid_typeid1_global_addr = hidden alias i8, ptr [[G]] -; X86: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 1 to ptr) +; X86: @__typeid_typeid1_align = hidden alias i8, inttoptr (i64 1 to ptr) ; X86: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 65 to ptr) ; CHECK: @__typeid_typeid1_byte_array = hidden alias i8, ptr @bits.1 ; X86: @__typeid_typeid1_bit_mask = hidden alias i8, inttoptr (i8 2 to ptr) ; CHECK: @__typeid_typeid2_global_addr = hidden alias i8, getelementptr (i8, ptr [[G]], i64 4) -; X86: @__typeid_typeid2_align = hidden alias i8, inttoptr (i8 2 to ptr) +; X86: @__typeid_typeid2_align = hidden alias i8, inttoptr (i64 2 to ptr) ; X86: @__typeid_typeid2_size_m1 = hidden alias i8, inttoptr (i64 257 to ptr) ; CHECK: @__typeid_typeid2_byte_array = hidden alias i8, ptr @bits ; X86: @__typeid_typeid2_bit_mask = hidden alias i8, inttoptr (i8 1 to ptr) diff --git a/llvm/test/Transforms/LowerTypeTests/export-icall.ll b/llvm/test/Transforms/LowerTypeTests/export-icall.ll index bb766fc2ea737..abd4097865907 100644 --- a/llvm/test/Transforms/LowerTypeTests/export-icall.ll +++ b/llvm/test/Transforms/LowerTypeTests/export-icall.ll @@ -37,7 +37,7 @@ define void @f3(i32 %x) !type !8 { ; CHECK-DAG: @__typeid_typeid1_global_addr = hidden alias i8, ptr [[JT1:.*]] -; CHECK-DAG: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 3 to ptr) +; CHECK-DAG: @__typeid_typeid1_align = hidden alias i8, inttoptr (i64 3 to ptr) ; CHECK-DAG: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 4 to ptr) ; CHECK-DAG: @h = alias void (i8), ptr [[JT1]] diff --git a/llvm/test/Transforms/LowerTypeTests/import.ll b/llvm/test/Transforms/LowerTypeTests/import.ll index 3c97f087d5c93..31b4f20e6fd7c 100644 --- a/llvm/test/Transforms/LowerTypeTests/import.ll +++ b/llvm/test/Transforms/LowerTypeTests/import.ll @@ -37,8 +37,7 @@ define i1 @allones7(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_allones7_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_allones7_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_allones7_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_allones7_size_m1 to i64) ; X86-NEXT: ret i1 [[TMP8]] ; @@ -59,8 +58,7 @@ define i1 @allones32(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_allones32_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_allones32_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_allones32_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_allones32_size_m1 to i64) ; X86-NEXT: ret i1 [[TMP8]] ; @@ -81,18 +79,17 @@ define i1 @bytearray7(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_bytearray7_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_bytearray7_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_bytearray7_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_bytearray7_size_m1 to i64) -; X86-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP14:%.*]] -; X86: 6: +; X86-NEXT: br i1 [[TMP8]], label %[[TMP9:.*]], label %[[TMP14:.*]] +; X86: [[TMP9]]: ; X86-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr @__typeid_bytearray7_byte_array, i64 [[TMP7]] ; X86-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; X86-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], ptrtoint (ptr @__typeid_bytearray7_bit_mask to i8) ; X86-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP12]], 0 -; X86-NEXT: br label [[TMP14]] -; X86: 11: -; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], [[TMP9]] ] +; X86-NEXT: br label %[[TMP14]] +; X86: [[TMP14]]: +; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], %[[TMP9]] ] ; X86-NEXT: ret i1 [[TMP15]] ; ; ARM-LABEL: define i1 @bytearray7( @@ -121,18 +118,17 @@ define i1 @bytearray32(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_bytearray32_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_bytearray32_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_bytearray32_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_bytearray32_size_m1 to i64) -; X86-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP14:%.*]] -; X86: 6: +; X86-NEXT: br i1 [[TMP8]], label %[[TMP9:.*]], label %[[TMP14:.*]] +; X86: [[TMP9]]: ; X86-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr @__typeid_bytearray32_byte_array, i64 [[TMP7]] ; X86-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; X86-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], ptrtoint (ptr @__typeid_bytearray32_bit_mask to i8) ; X86-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP12]], 0 -; X86-NEXT: br label [[TMP14]] -; X86: 11: -; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], [[TMP9]] ] +; X86-NEXT: br label %[[TMP14]] +; X86: [[TMP14]]: +; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], %[[TMP9]] ] ; X86-NEXT: ret i1 [[TMP15]] ; ; ARM-LABEL: define i1 @bytearray32( @@ -161,19 +157,18 @@ define i1 @inline5(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_inline5_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_inline5_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_inline5_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_inline5_size_m1 to i64) -; X86-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP15:%.*]] -; X86: 6: +; X86-NEXT: br i1 [[TMP8]], label %[[TMP9:.*]], label %[[TMP15:.*]] +; X86: [[TMP9]]: ; X86-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP7]] to i32 ; X86-NEXT: [[TMP11:%.*]] = and i32 [[TMP10]], 31 ; X86-NEXT: [[TMP12:%.*]] = shl i32 1, [[TMP11]] ; X86-NEXT: [[TMP13:%.*]] = and i32 ptrtoint (ptr @__typeid_inline5_inline_bits to i32), [[TMP12]] ; X86-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 -; X86-NEXT: br label [[TMP15]] -; X86: 12: -; X86-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP14]], [[TMP9]] ] +; X86-NEXT: br label %[[TMP15]] +; X86: [[TMP15]]: +; X86-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP14]], %[[TMP9]] ] ; X86-NEXT: ret i1 [[TMP16]] ; ; ARM-LABEL: define i1 @inline5( @@ -203,18 +198,17 @@ define i1 @inline6(ptr %p) { ; X86-SAME: ptr [[P:%.*]]) { ; X86-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; X86-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_inline6_global_addr to i64) -; X86-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_inline6_align to i8) to i64 -; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; X86-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_inline6_align to i64)) ; X86-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_inline6_size_m1 to i64) -; X86-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP14:%.*]] -; X86: 6: +; X86-NEXT: br i1 [[TMP8]], label %[[TMP9:.*]], label %[[TMP14:.*]] +; X86: [[TMP9]]: ; X86-NEXT: [[TMP10:%.*]] = and i64 [[TMP7]], 63 ; X86-NEXT: [[TMP11:%.*]] = shl i64 1, [[TMP10]] ; X86-NEXT: [[TMP12:%.*]] = and i64 ptrtoint (ptr @__typeid_inline6_inline_bits to i64), [[TMP11]] ; X86-NEXT: [[TMP13:%.*]] = icmp ne i64 [[TMP12]], 0 -; X86-NEXT: br label [[TMP14]] -; X86: 11: -; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], [[TMP9]] ] +; X86-NEXT: br label %[[TMP14]] +; X86: [[TMP14]]: +; X86-NEXT: [[TMP15:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP13]], %[[TMP9]] ] ; X86-NEXT: ret i1 [[TMP15]] ; ; ARM-LABEL: define i1 @inline6( diff --git a/llvm/test/Transforms/LowerTypeTests/simplify.ll b/llvm/test/Transforms/LowerTypeTests/simplify.ll index 5f2140caca274..c895ea6185f6c 100644 --- a/llvm/test/Transforms/LowerTypeTests/simplify.ll +++ b/llvm/test/Transforms/LowerTypeTests/simplify.ll @@ -11,19 +11,18 @@ define i1 @bytearray7(ptr %p) { ; CHECK-SAME: ptr [[P:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], ptrtoint (ptr @__typeid_bytearray7_global_addr to i64) -; CHECK-NEXT: [[TMP3:%.*]] = zext i8 ptrtoint (ptr @__typeid_bytearray7_align to i8) to i64 -; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 [[TMP3]]) +; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.fshr.i64(i64 [[TMP2]], i64 [[TMP2]], i64 ptrtoint (ptr @__typeid_bytearray7_align to i64)) ; CHECK-NEXT: [[TMP8:%.*]] = icmp ule i64 [[TMP7]], ptrtoint (ptr @__typeid_bytearray7_size_m1 to i64) -; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[F:%.*]] -; CHECK: 6: +; CHECK-NEXT: br i1 [[TMP8]], label %[[TMP9:.*]], label %[[F:.*]] +; CHECK: [[TMP9]]: ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr @__typeid_bytearray7_byte_array, i64 [[TMP7]] ; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = and i8 [[TMP11]], ptrtoint (ptr @__typeid_bytearray7_bit_mask to i8) ; CHECK-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP12]], 0 -; CHECK-NEXT: br i1 [[TMP13]], label [[T:%.*]], label [[F]] -; CHECK: t: +; CHECK-NEXT: br i1 [[TMP13]], label %[[T:.*]], label %[[F]] +; CHECK: [[T]]: ; CHECK-NEXT: ret i1 true -; CHECK: f: +; CHECK: [[F]]: ; CHECK-NEXT: ret i1 false ; %x = call i1 @llvm.type.test(ptr %p, metadata !"bytearray7") diff --git a/llvm/test/Transforms/SimplifyTypeTests/basic.ll b/llvm/test/Transforms/SimplifyTypeTests/basic.ll new file mode 100644 index 0000000000000..8f9dffa2ace98 --- /dev/null +++ b/llvm/test/Transforms/SimplifyTypeTests/basic.ll @@ -0,0 +1,46 @@ +; Test that a lowered type test for a type is simplified to true +; if the target is a constant member of that type. + +; RUN: opt -S %s -passes=simplify-type-tests | FileCheck %s + +; Test that the simplification does not occur if the type is wrong. + +; RUN: sed -e 's/"_ZTSFvvE"/"wrongtype"/g' %s | opt -S -passes=simplify-type-tests | FileCheck --check-prefix=WRONGTYPE %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@__typeid__ZTSFvvE_global_addr = external hidden global [0 x i8], code_model "small" + +define void @_Z2fpv.cfi() !type !0 { + ret void +} + +define i64 @main() { + %1 = icmp eq ptr @_Z2fpv, @__typeid__ZTSFvvE_global_addr + ; CHECK: br i1 true + ; WRONGTYPE: br i1 % + br i1 %1, label %3, label %2 + +2: + tail call void @llvm.ubsantrap(i8 2) + unreachable + +3: + ; CHECK: br i1 true + ; WRONGTYPE: br i1 % + %c = icmp eq i64 ptrtoint (ptr @_Z2fpv to i64), ptrtoint (ptr @__typeid__ZTSFvvE_global_addr to i64) + br i1 %c, label %4, label %2 + +4: + tail call void @_Z2fpv() + ; CHECK: ret i64 0 + ; WRONGTYPE: ret i64 sub + ret i64 sub (i64 ptrtoint (ptr @_Z2fpv to i64), i64 ptrtoint (ptr @__typeid__ZTSFvvE_global_addr to i64)) +} + +declare void @llvm.ubsantrap(i8 immarg) + +declare hidden void @_Z2fpv() + +!0 = !{i64 0, !"_ZTSFvvE"}