From 4b10a4c17781e389e5e67a0aa274ba00382ac149 Mon Sep 17 00:00:00 2001 From: Jacques Pienaar Date: Fri, 27 Feb 2026 18:44:38 +0200 Subject: [PATCH 01/58] [mlir] Enable specifying bytecode producer in mlir-opt. (#182846) --- mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h | 14 ++++++++++++++ mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 10 +++++++++- mlir/test/Bytecode/bytecode_producer.mlir | 5 +++++ mlir/test/CMakeLists.txt | 1 + mlir/test/lit.cfg.py | 1 + 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 mlir/test/Bytecode/bytecode_producer.mlir diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h index 79dfd7a2795f0..7e0b7024608c9 100644 --- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h +++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h @@ -128,6 +128,17 @@ class MlirOptMainConfig { return emitBytecodeVersion; } + /// Set the bytecode producer to use. + MlirOptMainConfig &emitBytecodeProducer(StringRef producer) { + emitBytecodeProducerFlag = producer.str(); + return *this; + } + std::optional bytecodeProducerToEmit() const { + if (emitBytecodeProducerFlag.empty()) + return std::nullopt; + return emitBytecodeProducerFlag; + } + /// Set the callback to populate the pass manager. MlirOptMainConfig & setPassPipelineSetupFn(std::function callback) { @@ -309,6 +320,9 @@ class MlirOptMainConfig { /// Emit bytecode at given version. std::optional emitBytecodeVersion = std::nullopt; + /// Emit bytecode with given producer. + std::string emitBytecodeProducerFlag = ""; + /// The callback to populate the pass manager. std::function passPipelineCallback; diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp index 560ef6effd2fb..f90abda3463ab 100644 --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -94,6 +94,11 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { cl::desc("Elide resources when generating bytecode"), cl::location(elideResourceDataFromBytecodeFlag), cl::init(false)); + static cl::opt emitBytecodeProducer( + "emit-bytecode-producer", + cl::desc("Use specified producer when generating bytecode output"), + cl::location(emitBytecodeProducerFlag), cl::init("")); + static cl::opt, /*ExternalStorage=*/true, BytecodeVersionParser> bytecodeVersion( @@ -602,7 +607,10 @@ performActions(raw_ostream &os, // Print the output. TimingScope outputTiming = timing.nest("Output"); if (config.shouldEmitBytecode()) { - BytecodeWriterConfig writerConfig(fallbackResourceMap); + std::optional producer = config.bytecodeProducerToEmit(); + BytecodeWriterConfig writerConfig = + producer ? BytecodeWriterConfig(fallbackResourceMap, producer.value()) + : BytecodeWriterConfig(fallbackResourceMap); if (auto v = config.bytecodeVersionToEmit()) writerConfig.setDesiredBytecodeVersion(*v); if (config.shouldElideResourceDataFromBytecode()) diff --git a/mlir/test/Bytecode/bytecode_producer.mlir b/mlir/test/Bytecode/bytecode_producer.mlir new file mode 100644 index 0000000000000..ba13dd3de9dd9 --- /dev/null +++ b/mlir/test/Bytecode/bytecode_producer.mlir @@ -0,0 +1,5 @@ +// RUN: mlir-opt %s -emit-bytecode -emit-bytecode-producer="MyCustomProducer" | llvm-strings | FileCheck %s + +// CHECK: MyCustomProducer + +module {} diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt index dfa6a9943543b..55534b9910503 100644 --- a/mlir/test/CMakeLists.txt +++ b/mlir/test/CMakeLists.txt @@ -101,6 +101,7 @@ configure_lit_site_cfg( ) set(MLIR_TEST_DEPENDS + llvm-strings mlir-capi-ir-test mlir-capi-irdl-test mlir-capi-llvm-test diff --git a/mlir/test/lit.cfg.py b/mlir/test/lit.cfg.py index 9c5bee169efe0..174623eb347b9 100644 --- a/mlir/test/lit.cfg.py +++ b/mlir/test/lit.cfg.py @@ -187,6 +187,7 @@ def find_real_python_interpreter(): llvm_config.with_environment("PATH", dirs, append_path=True) tools = [ + "llvm-strings", "mlir-tblgen", "mlir-translate", "mlir-lsp-server", From 9c53215d213189d1f62e8f6ee7ba73a089ac2269 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 27 Feb 2026 16:49:54 +0000 Subject: [PATCH 02/58] [VPlan] Remove manual region removal when simplifying for VF and UF. (#181252) Replace manual region dissolution code in simplifyBranchConditionForVFAndUF with using general removeBranchOnConst. simplifyBranchConditionForVFAndUF now just creates a (BranchOnCond true) or updates BranchOnTwoConds. The loop then gets automatically removed by running removeBranchOnConst. This removes a bunch of special logic to handle header phi replacements and CFG updates. With the new code, there's no restriction on what kind of header phi recipes the loop contains. Note that VPEVLBasedIVRecipe needs to be marked as readnone. This is technically unrelated, but I could not find an independent test that would be impacted. The code to deal with epilogue resume values now needs updating, because we may simplify a reduction directly to the start value. PR: https://github.com/llvm/llvm-project/pull/181252 --- .../Transforms/Vectorize/LoopVectorize.cpp | 43 ++- .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 2 + .../Transforms/Vectorize/VPlanTransforms.cpp | 93 ++---- .../Transforms/Vectorize/VPlanTransforms.h | 5 + .../AArch64/clamped-trip-count.ll | 40 +-- .../AArch64/force-target-instruction-cost.ll | 8 +- .../AArch64/low_trip_count_predicates.ll | 18 +- .../AArch64/mul-simplification.ll | 10 +- .../LoopVectorize/AArch64/optsize_minsize.ll | 209 +++++-------- .../replicating-load-store-costs-apple.ll | 19 +- .../AArch64/replicating-load-store-costs.ll | 19 +- .../LoopVectorize/RISCV/low-trip-count.ll | 14 +- ...ctor-loop-backedge-elimination-with-evl.ll | 15 +- .../LoopVectorize/X86/cost-model.ll | 38 +-- .../LoopVectorize/X86/load-deref-pred.ll | 110 +++---- .../epilog-vectorization-reductions.ll | 196 +++++++++++- .../LoopVectorize/iv-select-cmp-decreasing.ll | 292 ++++++------------ ...eref-pred-poison-ub-ops-feeding-pointer.ll | 179 ++++------- .../reduction-minmax-users-and-predicated.ll | 58 ++-- .../single-early-exit-cond-poison.ll | 8 +- ...or-loop-backedge-elimination-early-exit.ll | 95 +++--- .../vector-loop-backedge-elimination.ll | 266 ++++++++++++++++ 22 files changed, 921 insertions(+), 816 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 0debab4a2a0ee..f68d3ad2a74fb 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -7371,21 +7371,39 @@ static void fixReductionScalarResumeWhenVectorizingEpilog( vputils::findRecipe(BackedgeVal, IsaPred)); if (!EpiRedHeaderPhi) { match(BackedgeVal, - VPlanPatternMatch::m_Select(VPlanPatternMatch::m_VPValue(), - VPlanPatternMatch::m_VPValue(BackedgeVal), - VPlanPatternMatch::m_VPValue())); - EpiRedHeaderPhi = cast( + m_Select(m_VPValue(), m_VPValue(BackedgeVal), m_VPValue())); + EpiRedHeaderPhi = cast_if_present( vputils::findRecipe(BackedgeVal, IsaPred)); } + // Look through Broadcast or ReductionStartVector to get the underlying + // start value. + auto GetStartValue = [](VPValue *V) -> Value * { + VPValue *Start; + if (match(V, m_VPInstruction( + m_VPValue(Start), m_VPValue(), m_VPValue())) || + match(V, m_Broadcast(m_VPValue(Start)))) + return Start->getUnderlyingValue(); + return V->getUnderlyingValue(); + }; + Value *MainResumeValue; - if (auto *VPI = dyn_cast(EpiRedHeaderPhi->getStartValue())) { - assert((VPI->getOpcode() == VPInstruction::Broadcast || - VPI->getOpcode() == VPInstruction::ReductionStartVector) && - "unexpected start recipe"); - MainResumeValue = VPI->getOperand(0)->getUnderlyingValue(); - } else - MainResumeValue = EpiRedHeaderPhi->getStartValue()->getUnderlyingValue(); + if (EpiRedHeaderPhi) { + MainResumeValue = GetStartValue(EpiRedHeaderPhi->getStartValue()); + } else { + // The epilogue vector loop was dissolved (single-iteration). The + // reduction header phi was replaced by its start value. Look for a + // Broadcast or ReductionStartVector in BackedgeVal or its operands. + Value *FromOperand = nullptr; + if (auto *BackedgeR = BackedgeVal->getDefiningRecipe()) { + auto *It = find_if(BackedgeR->operands(), [&](VPValue *Op) { + return GetStartValue(Op) != Op->getUnderlyingValue(); + }); + if (It != BackedgeR->op_end()) + FromOperand = GetStartValue(*It); + } + MainResumeValue = FromOperand ? FromOperand : GetStartValue(BackedgeVal); + } if (EpiRedResult->getOpcode() == VPInstruction::ComputeAnyOfResult) { [[maybe_unused]] Value *StartV = EpiRedResult->getOperand(0)->getLiveInIRValue(); @@ -7467,6 +7485,8 @@ DenseMap LoopVectorizationPlanner::executePlan( VPlanTransforms::expandBranchOnTwoConds(BestVPlan); // Convert loops with variable-length stepping after regions are dissolved. VPlanTransforms::convertToVariableLengthStep(BestVPlan); + // Remove dead edges for single-iteration loops with BranchOnCond(true). + VPlanTransforms::removeBranchOnConst(BestVPlan); VPlanTransforms::materializeBackedgeTakenCount(BestVPlan, VectorPH); VPlanTransforms::materializeVectorTripCount( BestVPlan, VectorPH, CM.foldTailByMasking(), @@ -7474,6 +7494,7 @@ DenseMap LoopVectorizationPlanner::executePlan( VPlanTransforms::materializeFactors(BestVPlan, VectorPH, BestVF); VPlanTransforms::cse(BestVPlan); VPlanTransforms::simplifyRecipes(BestVPlan); + VPlanTransforms::simplifyKnownEVL(BestVPlan, BestVF, PSE); // 0. Generate SCEV-dependent code in the entry, including TripCount, before // making any changes to the CFG. diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index eb1b51c40cec4..4343c13d795b5 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -128,6 +128,7 @@ bool VPRecipeBase::mayReadFromMemory() const { return cast(this)->mayReadFromMemory(); case VPBranchOnMaskSC: case VPDerivedIVSC: + case VPCurrentIterationPHISC: case VPFirstOrderRecurrencePHISC: case VPReductionPHISC: case VPPredInstPHISC: @@ -165,6 +166,7 @@ bool VPRecipeBase::mayHaveSideEffects() const { return cast(this)->mayHaveSideEffects(); case VPActiveLaneMaskPHISC: case VPDerivedIVSC: + case VPCurrentIterationPHISC: case VPFirstOrderRecurrencePHISC: case VPReductionPHISC: case VPPredInstPHISC: diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index 4c393f2f6f05a..6ca0e1864409a 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -1469,12 +1469,6 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) { return; } - if (auto *Phi = dyn_cast(Def)) { - if (Phi->getOperand(0) == Phi->getOperand(1)) - Phi->replaceAllUsesWith(Phi->getOperand(0)); - return; - } - // Simplify MaskedCond with no block mask to its single operand. if (match(Def, m_VPInstruction()) && !cast(Def)->isMasked()) @@ -1523,9 +1517,15 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) { return; } - if (isa(Def)) { - if (Def->getNumOperands() == 1) + if (isa(Def)) { + if (Def->getNumOperands() == 1) { Def->replaceAllUsesWith(Def->getOperand(0)); + return; + } + if (auto *Phi = dyn_cast(Def)) { + if (all_equal(Phi->incoming_values())) + Phi->replaceAllUsesWith(Phi->getOperand(0)); + } return; } @@ -2097,72 +2097,16 @@ static bool simplifyBranchConditionForVFAndUF(VPlan &Plan, ElementCount BestVF, return false; } - // The vector loop region only executes once. If possible, completely remove - // the region, otherwise replace the terminator controlling the latch with - // (BranchOnCond true). - // TODO: VPWidenIntOrFpInductionRecipe is only partially supported; add - // support for other non-canonical widen induction recipes (e.g., - // VPWidenPointerInductionRecipe). - // TODO: fold branch-on-constant after dissolving region. - auto *Header = cast(VectorRegion->getEntry()); - if (all_of(Header->phis(), [](VPRecipeBase &Phi) { - if (auto *R = dyn_cast(&Phi)) - return R->isCanonical(); - return isa(&Phi); - })) { - for (VPRecipeBase &HeaderR : make_early_inc_range(Header->phis())) { - if (auto *R = dyn_cast(&HeaderR)) { - VPBuilder Builder(Plan.getVectorPreheader()); - VPValue *StepV = Builder.createNaryOp(VPInstruction::StepVector, {}, - R->getScalarType()); - HeaderR.getVPSingleValue()->replaceAllUsesWith(StepV); - HeaderR.eraseFromParent(); - continue; - } - auto *Phi = cast(&HeaderR); - HeaderR.getVPSingleValue()->replaceAllUsesWith(Phi->getIncomingValue(0)); - HeaderR.eraseFromParent(); - } - - VPBlockBase *Preheader = VectorRegion->getSinglePredecessor(); - SmallVector Exits = to_vector(VectorRegion->getSuccessors()); - VPBlockUtils::disconnectBlocks(Preheader, VectorRegion); - for (VPBlockBase *Exit : Exits) - VPBlockUtils::disconnectBlocks(VectorRegion, Exit); - - for (VPBlockBase *B : vp_depth_first_shallow(VectorRegion->getEntry())) - B->setParent(nullptr); - - VPBlockUtils::connectBlocks(Preheader, Header); - - for (VPBlockBase *Exit : Exits) - VPBlockUtils::connectBlocks(ExitingVPBB, Exit); - - // Replace terminating branch-on-two-conds with branch-on-cond to early - // exit. - if (Exits.size() != 1) { - assert(match(Term, m_BranchOnTwoConds()) && Exits.size() == 2 && - "BranchOnTwoConds needs 2 remaining exits"); - VPBuilder(Term).createNaryOp(VPInstruction::BranchOnCond, - Term->getOperand(0)); - } - VPlanTransforms::simplifyRecipes(Plan); - } else { - // The vector region contains header phis for which we cannot remove the - // loop region yet. - - // For BranchOnTwoConds, set the latch exit condition to true directly. - if (match(Term, m_BranchOnTwoConds())) { - Term->setOperand(1, Plan.getTrue()); - return true; - } - - auto *BOC = new VPInstruction(VPInstruction::BranchOnCond, {Plan.getTrue()}, - {}, {}, Term->getDebugLoc()); - ExitingVPBB->appendRecipe(BOC); + // The vector loop region only executes once. Convert terminator of the + // exiting block to exit in the first iteration. + if (match(Term, m_BranchOnTwoConds())) { + Term->setOperand(1, Plan.getTrue()); + return true; } + auto *BOC = new VPInstruction(VPInstruction::BranchOnCond, Plan.getTrue(), {}, + {}, Term->getDebugLoc()); + ExitingVPBB->appendRecipe(BOC); Term->eraseFromParent(); return true; @@ -2170,8 +2114,8 @@ static bool simplifyBranchConditionForVFAndUF(VPlan &Plan, ElementCount BestVF, /// From the definition of llvm.experimental.get.vector.length, /// VPInstruction::ExplicitVectorLength(%AVL) = %AVL when %AVL <= VF. -static bool simplifyKnownEVL(VPlan &Plan, ElementCount VF, - PredicatedScalarEvolution &PSE) { +bool VPlanTransforms::simplifyKnownEVL(VPlan &Plan, ElementCount VF, + PredicatedScalarEvolution &PSE) { for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly( vp_depth_first_deep(Plan.getEntry()))) { for (VPRecipeBase &R : *VPBB) { @@ -2206,7 +2150,6 @@ void VPlanTransforms::optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF, bool MadeChange = tryToReplaceALMWithWideALM(Plan, BestVF, BestUF); MadeChange |= simplifyBranchConditionForVFAndUF(Plan, BestVF, BestUF, PSE); MadeChange |= optimizeVectorInductionWidthForTCAndVFUF(Plan, BestVF, BestUF); - MadeChange |= simplifyKnownEVL(Plan, BestVF, PSE); if (MadeChange) { Plan.setVF(BestVF); diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h index 0dce486cb1c2c..b516adb83d832 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h @@ -239,6 +239,11 @@ struct VPlanTransforms { unsigned BestUF, PredicatedScalarEvolution &PSE); + /// Try to simplify VPInstruction::ExplicitVectorLength recipes when the AVL + /// is known to be <= VF, replacing them with the AVL directly. + static bool simplifyKnownEVL(VPlan &Plan, ElementCount VF, + PredicatedScalarEvolution &PSE); + /// Apply VPlan-to-VPlan optimizations to \p Plan, including induction recipe /// optimizations, dead recipe removal, replicate region optimizations and /// block merging. diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/clamped-trip-count.ll b/llvm/test/Transforms/LoopVectorize/AArch64/clamped-trip-count.ll index e054c916de6e0..d54e8582676d6 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/clamped-trip-count.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/clamped-trip-count.ll @@ -8,28 +8,17 @@ define void @clamped_tc_8(ptr nocapture %dst, i32 %n, i64 %val) vscale_range(1,1 ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 3 ; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call @llvm.get.active.lane.mask.nxv8i1.i64(i64 0, i64 8) ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement poison, i64 [[VAL]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector [[BROADCAST_SPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.stepvector.nxv8i64() -; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP1]], i64 0 -; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi [ [[TMP8]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[DST]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw [[VEC_IND]], splat (i64 3) +; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw [[TMP8]], splat (i64 3) ; CHECK-NEXT: [[TMP11:%.*]] = lshr [[BROADCAST_SPLAT]], [[TMP10]] ; CHECK-NEXT: [[TMP14:%.*]] = trunc [[TMP11]] to -; CHECK-NEXT: call void @llvm.masked.store.nxv8i8.p0( [[TMP14]], ptr align 1 [[NEXT_GEP]], [[ACTIVE_LANE_MASK]]) -; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP1]] -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[INDEX_NEXT]], i64 8) -; CHECK-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: call void @llvm.masked.store.nxv8i8.p0( [[TMP14]], ptr align 1 [[DST]], [[ACTIVE_LANE_MASK_ENTRY]]) +; CHECK-NEXT: br label [[MIDDLE_BLOCK:%.*]] ; CHECK: middle.block: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup: @@ -68,28 +57,17 @@ define void @clamped_tc_max_8(ptr nocapture %dst, i32 %n, i64 %val) vscale_range ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SHR]] to i64 ; CHECK-NEXT: br label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 3 ; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call @llvm.get.active.lane.mask.nxv8i1.i64(i64 0, i64 [[WIDE_TRIP_COUNT]]) ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement poison, i64 [[VAL]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector [[BROADCAST_SPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: [[TMP8:%.*]] = call @llvm.stepvector.nxv8i64() -; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i64 [[TMP1]], i64 0 -; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi [ [[TMP8]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[DST]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw [[VEC_IND]], splat (i64 3) +; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw [[TMP8]], splat (i64 3) ; CHECK-NEXT: [[TMP11:%.*]] = lshr [[BROADCAST_SPLAT]], [[TMP10]] ; CHECK-NEXT: [[TMP14:%.*]] = trunc [[TMP11]] to -; CHECK-NEXT: call void @llvm.masked.store.nxv8i8.p0( [[TMP14]], ptr align 1 [[NEXT_GEP]], [[ACTIVE_LANE_MASK]]) -; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP1]] -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[INDEX_NEXT]], i64 [[WIDE_TRIP_COUNT]]) -; CHECK-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK-NEXT: call void @llvm.masked.store.nxv8i8.p0( [[TMP14]], ptr align 1 [[DST]], [[ACTIVE_LANE_MASK_ENTRY]]) +; CHECK-NEXT: br label [[MIDDLE_BLOCK:%.*]] ; CHECK: middle.block: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup.loopexit: @@ -124,9 +102,3 @@ for.body: ; preds = %for.body.preheader, for.cond.cleanup: ; preds = %for.body ret void } -;. -; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} -; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} -; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]], [[META2]]} -;. diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/force-target-instruction-cost.ll b/llvm/test/Transforms/LoopVectorize/AArch64/force-target-instruction-cost.ll index e1eb86e2e3a57..c066e0b41013d 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/force-target-instruction-cost.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/force-target-instruction-cost.ll @@ -12,11 +12,9 @@ define double @test_reduction_costs() { ; COMMON: [[VECTOR_PH]]: ; COMMON-NEXT: br label %[[VECTOR_BODY:.*]] ; COMMON: [[VECTOR_BODY]]: -; COMMON-NEXT: [[VEC_PHI:%.*]] = phi double [ 0.000000e+00, %[[VECTOR_PH]] ], [ [[TMP0:%.*]], %[[VECTOR_BODY]] ] -; COMMON-NEXT: [[VEC_PHI1:%.*]] = phi double [ 0.000000e+00, %[[VECTOR_PH]] ], [ [[TMP1:%.*]], %[[VECTOR_BODY]] ] -; COMMON-NEXT: [[TMP0]] = call double @llvm.vector.reduce.fadd.v2f64(double [[VEC_PHI]], <2 x double> splat (double 3.000000e+00)) -; COMMON-NEXT: [[TMP1]] = call double @llvm.vector.reduce.fadd.v2f64(double [[VEC_PHI1]], <2 x double> splat (double 9.000000e+00)) -; COMMON-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; COMMON-NEXT: [[TMP0:%.*]] = call double @llvm.vector.reduce.fadd.v2f64(double 0.000000e+00, <2 x double> splat (double 3.000000e+00)) +; COMMON-NEXT: [[TMP1:%.*]] = call double @llvm.vector.reduce.fadd.v2f64(double 0.000000e+00, <2 x double> splat (double 9.000000e+00)) +; COMMON-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; COMMON: [[MIDDLE_BLOCK]]: ; COMMON-NEXT: br label %[[EXIT:.*]] ; COMMON: [[EXIT]]: diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/low_trip_count_predicates.ll b/llvm/test/Transforms/LoopVectorize/AArch64/low_trip_count_predicates.ll index c340cfc9ad6cc..6acda0d4b3294 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/low_trip_count_predicates.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/low_trip_count_predicates.ll @@ -464,13 +464,9 @@ define i32 @tc4(ptr noundef readonly captures(none) %tmp) vscale_range(1,16) { ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP3:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP]], i64 [[INDEX]] -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[ARRAYIDX1]], align 4 -; CHECK-NEXT: [[TMP3]] = add <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> zeroinitializer, [[WIDE_LOAD]] +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP3]]) ; CHECK-NEXT: br label %[[EXIT:.*]] @@ -509,7 +505,7 @@ define i32 @tc4_from_profile(ptr noundef readonly captures(none) %tmp, i64 %N) v ; CHECK-NEXT: [[ADD]] = add i32 [[SUM_0179]], [[TMP0]] ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[FOR_BODY]], !prof [[PROF9:![0-9]+]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[FOR_BODY]], !prof [[PROF8:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], %[[FOR_BODY]] ] ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] @@ -546,8 +542,7 @@ exit: ; preds = %for.body ; CHECK-VS1: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]]} ; CHECK-VS1: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} ; CHECK-VS1: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]]} -; CHECK-VS1: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]} -; CHECK-VS1: [[PROF9]] = !{!"branch_weights", i32 10, i32 30} +; CHECK-VS1: [[PROF8]] = !{!"branch_weights", i32 10, i32 30} ;. ; CHECK-VS2: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ; CHECK-VS2: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} @@ -557,6 +552,5 @@ exit: ; preds = %for.body ; CHECK-VS2: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]]} ; CHECK-VS2: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} ; CHECK-VS2: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]]} -; CHECK-VS2: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]} -; CHECK-VS2: [[PROF9]] = !{!"branch_weights", i32 10, i32 30} +; CHECK-VS2: [[PROF8]] = !{!"branch_weights", i32 10, i32 30} ;. diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/mul-simplification.ll b/llvm/test/Transforms/LoopVectorize/AArch64/mul-simplification.ll index c4d06254a0d30..4b25bec39e51b 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/mul-simplification.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/mul-simplification.ll @@ -51,17 +51,17 @@ define i32 @add_reduction_select_operand_constant_but_non_uniform() { ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP2:%.*]] = phi <4 x i32> [ , %[[VECTOR_PH]] ], [ [[TMP2]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP1:%.*]] = phi <4 x i32> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP1]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , %[[VECTOR_PH]] ], [ [[VEC_PHI]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x i32> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[VEC_PHI1]], %[[VECTOR_BODY]] ] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 8 ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[INDEX_NEXT]], 64 ; CHECK-NEXT: br i1 [[TMP0]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[VEC_PHI1]], [[VEC_PHI]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: ret i32 [[TMP3]] +; CHECK-NEXT: ret i32 [[TMP1]] ; entry: br label %loop diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/optsize_minsize.ll b/llvm/test/Transforms/LoopVectorize/AArch64/optsize_minsize.ll index 135d9d526954e..1805243cbbca0 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/optsize_minsize.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/optsize_minsize.ll @@ -196,165 +196,124 @@ define void @tail_predicate_without_optsize(ptr %p, i8 %a, i8 %b, i8 %c, i32 %n) ; DEFAULT-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <16 x i8> [[BROADCAST_SPLATINSERT5]], <16 x i8> poison, <16 x i32> zeroinitializer ; DEFAULT-NEXT: br label %[[VECTOR_BODY:.*]] ; DEFAULT: [[VECTOR_BODY]]: -; DEFAULT-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE35:.*]] ] -; DEFAULT-NEXT: [[VEC_IND:%.*]] = phi <16 x i8> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE35]] ] -; DEFAULT-NEXT: [[VEC_IND1:%.*]] = phi <16 x i8> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT36:%.*]], %[[PRED_STORE_CONTINUE35]] ] -; DEFAULT-NEXT: [[TMP0:%.*]] = icmp ule <16 x i8> [[VEC_IND]], splat (i8 14) -; DEFAULT-NEXT: [[TMP1:%.*]] = mul <16 x i8> [[BROADCAST_SPLAT]], [[VEC_IND1]] -; DEFAULT-NEXT: [[TMP2:%.*]] = lshr <16 x i8> [[VEC_IND1]], splat (i8 1) -; DEFAULT-NEXT: [[TMP3:%.*]] = mul <16 x i8> [[TMP2]], [[BROADCAST_SPLAT4]] +; DEFAULT-NEXT: [[TMP1:%.*]] = mul <16 x i8> [[BROADCAST_SPLAT]], +; DEFAULT-NEXT: [[TMP3:%.*]] = mul <16 x i8> , [[BROADCAST_SPLAT4]] ; DEFAULT-NEXT: [[TMP4:%.*]] = add <16 x i8> [[TMP3]], [[TMP1]] -; DEFAULT-NEXT: [[TMP5:%.*]] = lshr <16 x i8> [[VEC_IND1]], splat (i8 2) -; DEFAULT-NEXT: [[TMP6:%.*]] = mul <16 x i8> [[TMP5]], [[BROADCAST_SPLAT6]] +; DEFAULT-NEXT: [[TMP6:%.*]] = mul <16 x i8> , [[BROADCAST_SPLAT6]] ; DEFAULT-NEXT: [[TMP7:%.*]] = add <16 x i8> [[TMP4]], [[TMP6]] -; DEFAULT-NEXT: [[TMP8:%.*]] = extractelement <16 x i1> [[TMP0]], i32 0 -; DEFAULT-NEXT: br i1 [[TMP8]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; DEFAULT: [[PRED_STORE_IF]]: -; DEFAULT-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 0 -; DEFAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP9]] +; DEFAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 0 ; DEFAULT-NEXT: [[TMP11:%.*]] = extractelement <16 x i8> [[TMP7]], i32 0 ; DEFAULT-NEXT: store i8 [[TMP11]], ptr [[TMP10]], align 1 ; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE]] ; DEFAULT: [[PRED_STORE_CONTINUE]]: -; DEFAULT-NEXT: [[TMP12:%.*]] = extractelement <16 x i1> [[TMP0]], i32 1 -; DEFAULT-NEXT: br i1 [[TMP12]], label %[[PRED_STORE_IF6:.*]], label %[[PRED_STORE_CONTINUE7:.*]] -; DEFAULT: [[PRED_STORE_IF6]]: -; DEFAULT-NEXT: [[TMP13:%.*]] = add i64 [[INDEX]], 1 -; DEFAULT-NEXT: [[TMP14:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP13]] +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF5:.*]], label %[[PRED_STORE_CONTINUE6:.*]] +; DEFAULT: [[PRED_STORE_IF5]]: +; DEFAULT-NEXT: [[TMP14:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1 ; DEFAULT-NEXT: [[TMP15:%.*]] = extractelement <16 x i8> [[TMP7]], i32 1 ; DEFAULT-NEXT: store i8 [[TMP15]], ptr [[TMP14]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE7]] -; DEFAULT: [[PRED_STORE_CONTINUE7]]: -; DEFAULT-NEXT: [[TMP16:%.*]] = extractelement <16 x i1> [[TMP0]], i32 2 -; DEFAULT-NEXT: br i1 [[TMP16]], label %[[PRED_STORE_IF8:.*]], label %[[PRED_STORE_CONTINUE9:.*]] -; DEFAULT: [[PRED_STORE_IF8]]: -; DEFAULT-NEXT: [[TMP17:%.*]] = add i64 [[INDEX]], 2 -; DEFAULT-NEXT: [[TMP18:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP17]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE6]] +; DEFAULT: [[PRED_STORE_CONTINUE6]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF7:.*]], label %[[PRED_STORE_CONTINUE8:.*]] +; DEFAULT: [[PRED_STORE_IF7]]: +; DEFAULT-NEXT: [[TMP18:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2 ; DEFAULT-NEXT: [[TMP19:%.*]] = extractelement <16 x i8> [[TMP7]], i32 2 ; DEFAULT-NEXT: store i8 [[TMP19]], ptr [[TMP18]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE9]] -; DEFAULT: [[PRED_STORE_CONTINUE9]]: -; DEFAULT-NEXT: [[TMP20:%.*]] = extractelement <16 x i1> [[TMP0]], i32 3 -; DEFAULT-NEXT: br i1 [[TMP20]], label %[[PRED_STORE_IF10:.*]], label %[[PRED_STORE_CONTINUE11:.*]] -; DEFAULT: [[PRED_STORE_IF10]]: -; DEFAULT-NEXT: [[TMP21:%.*]] = add i64 [[INDEX]], 3 -; DEFAULT-NEXT: [[TMP22:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP21]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE8]] +; DEFAULT: [[PRED_STORE_CONTINUE8]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF9:.*]], label %[[PRED_STORE_CONTINUE10:.*]] +; DEFAULT: [[PRED_STORE_IF9]]: +; DEFAULT-NEXT: [[TMP22:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 3 ; DEFAULT-NEXT: [[TMP23:%.*]] = extractelement <16 x i8> [[TMP7]], i32 3 ; DEFAULT-NEXT: store i8 [[TMP23]], ptr [[TMP22]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE11]] -; DEFAULT: [[PRED_STORE_CONTINUE11]]: -; DEFAULT-NEXT: [[TMP24:%.*]] = extractelement <16 x i1> [[TMP0]], i32 4 -; DEFAULT-NEXT: br i1 [[TMP24]], label %[[PRED_STORE_IF12:.*]], label %[[PRED_STORE_CONTINUE13:.*]] -; DEFAULT: [[PRED_STORE_IF12]]: -; DEFAULT-NEXT: [[TMP25:%.*]] = add i64 [[INDEX]], 4 -; DEFAULT-NEXT: [[TMP26:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP25]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE10]] +; DEFAULT: [[PRED_STORE_CONTINUE10]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF11:.*]], label %[[PRED_STORE_CONTINUE12:.*]] +; DEFAULT: [[PRED_STORE_IF11]]: +; DEFAULT-NEXT: [[TMP26:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4 ; DEFAULT-NEXT: [[TMP27:%.*]] = extractelement <16 x i8> [[TMP7]], i32 4 ; DEFAULT-NEXT: store i8 [[TMP27]], ptr [[TMP26]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE13]] -; DEFAULT: [[PRED_STORE_CONTINUE13]]: -; DEFAULT-NEXT: [[TMP28:%.*]] = extractelement <16 x i1> [[TMP0]], i32 5 -; DEFAULT-NEXT: br i1 [[TMP28]], label %[[PRED_STORE_IF14:.*]], label %[[PRED_STORE_CONTINUE15:.*]] -; DEFAULT: [[PRED_STORE_IF14]]: -; DEFAULT-NEXT: [[TMP29:%.*]] = add i64 [[INDEX]], 5 -; DEFAULT-NEXT: [[TMP30:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP29]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE12]] +; DEFAULT: [[PRED_STORE_CONTINUE12]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF13:.*]], label %[[PRED_STORE_CONTINUE14:.*]] +; DEFAULT: [[PRED_STORE_IF13]]: +; DEFAULT-NEXT: [[TMP30:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 5 ; DEFAULT-NEXT: [[TMP31:%.*]] = extractelement <16 x i8> [[TMP7]], i32 5 ; DEFAULT-NEXT: store i8 [[TMP31]], ptr [[TMP30]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE15]] -; DEFAULT: [[PRED_STORE_CONTINUE15]]: -; DEFAULT-NEXT: [[TMP32:%.*]] = extractelement <16 x i1> [[TMP0]], i32 6 -; DEFAULT-NEXT: br i1 [[TMP32]], label %[[PRED_STORE_IF16:.*]], label %[[PRED_STORE_CONTINUE17:.*]] -; DEFAULT: [[PRED_STORE_IF16]]: -; DEFAULT-NEXT: [[TMP33:%.*]] = add i64 [[INDEX]], 6 -; DEFAULT-NEXT: [[TMP34:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP33]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE14]] +; DEFAULT: [[PRED_STORE_CONTINUE14]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF15:.*]], label %[[PRED_STORE_CONTINUE16:.*]] +; DEFAULT: [[PRED_STORE_IF15]]: +; DEFAULT-NEXT: [[TMP34:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 6 ; DEFAULT-NEXT: [[TMP35:%.*]] = extractelement <16 x i8> [[TMP7]], i32 6 ; DEFAULT-NEXT: store i8 [[TMP35]], ptr [[TMP34]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE17]] -; DEFAULT: [[PRED_STORE_CONTINUE17]]: -; DEFAULT-NEXT: [[TMP36:%.*]] = extractelement <16 x i1> [[TMP0]], i32 7 -; DEFAULT-NEXT: br i1 [[TMP36]], label %[[PRED_STORE_IF18:.*]], label %[[PRED_STORE_CONTINUE19:.*]] -; DEFAULT: [[PRED_STORE_IF18]]: -; DEFAULT-NEXT: [[TMP37:%.*]] = add i64 [[INDEX]], 7 -; DEFAULT-NEXT: [[TMP38:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP37]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE16]] +; DEFAULT: [[PRED_STORE_CONTINUE16]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF17:.*]], label %[[PRED_STORE_CONTINUE18:.*]] +; DEFAULT: [[PRED_STORE_IF17]]: +; DEFAULT-NEXT: [[TMP38:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 7 ; DEFAULT-NEXT: [[TMP39:%.*]] = extractelement <16 x i8> [[TMP7]], i32 7 ; DEFAULT-NEXT: store i8 [[TMP39]], ptr [[TMP38]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE19]] -; DEFAULT: [[PRED_STORE_CONTINUE19]]: -; DEFAULT-NEXT: [[TMP40:%.*]] = extractelement <16 x i1> [[TMP0]], i32 8 -; DEFAULT-NEXT: br i1 [[TMP40]], label %[[PRED_STORE_IF20:.*]], label %[[PRED_STORE_CONTINUE21:.*]] -; DEFAULT: [[PRED_STORE_IF20]]: -; DEFAULT-NEXT: [[TMP41:%.*]] = add i64 [[INDEX]], 8 -; DEFAULT-NEXT: [[TMP42:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP41]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE18]] +; DEFAULT: [[PRED_STORE_CONTINUE18]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF19:.*]], label %[[PRED_STORE_CONTINUE20:.*]] +; DEFAULT: [[PRED_STORE_IF19]]: +; DEFAULT-NEXT: [[TMP42:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 ; DEFAULT-NEXT: [[TMP43:%.*]] = extractelement <16 x i8> [[TMP7]], i32 8 ; DEFAULT-NEXT: store i8 [[TMP43]], ptr [[TMP42]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE21]] -; DEFAULT: [[PRED_STORE_CONTINUE21]]: -; DEFAULT-NEXT: [[TMP44:%.*]] = extractelement <16 x i1> [[TMP0]], i32 9 -; DEFAULT-NEXT: br i1 [[TMP44]], label %[[PRED_STORE_IF22:.*]], label %[[PRED_STORE_CONTINUE23:.*]] -; DEFAULT: [[PRED_STORE_IF22]]: -; DEFAULT-NEXT: [[TMP45:%.*]] = add i64 [[INDEX]], 9 -; DEFAULT-NEXT: [[TMP46:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP45]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE20]] +; DEFAULT: [[PRED_STORE_CONTINUE20]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF21:.*]], label %[[PRED_STORE_CONTINUE22:.*]] +; DEFAULT: [[PRED_STORE_IF21]]: +; DEFAULT-NEXT: [[TMP46:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 ; DEFAULT-NEXT: [[TMP47:%.*]] = extractelement <16 x i8> [[TMP7]], i32 9 ; DEFAULT-NEXT: store i8 [[TMP47]], ptr [[TMP46]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE23]] -; DEFAULT: [[PRED_STORE_CONTINUE23]]: -; DEFAULT-NEXT: [[TMP48:%.*]] = extractelement <16 x i1> [[TMP0]], i32 10 -; DEFAULT-NEXT: br i1 [[TMP48]], label %[[PRED_STORE_IF24:.*]], label %[[PRED_STORE_CONTINUE25:.*]] -; DEFAULT: [[PRED_STORE_IF24]]: -; DEFAULT-NEXT: [[TMP49:%.*]] = add i64 [[INDEX]], 10 -; DEFAULT-NEXT: [[TMP50:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP49]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE22]] +; DEFAULT: [[PRED_STORE_CONTINUE22]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF23:.*]], label %[[PRED_STORE_CONTINUE24:.*]] +; DEFAULT: [[PRED_STORE_IF23]]: +; DEFAULT-NEXT: [[TMP50:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 10 ; DEFAULT-NEXT: [[TMP51:%.*]] = extractelement <16 x i8> [[TMP7]], i32 10 ; DEFAULT-NEXT: store i8 [[TMP51]], ptr [[TMP50]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE25]] -; DEFAULT: [[PRED_STORE_CONTINUE25]]: -; DEFAULT-NEXT: [[TMP52:%.*]] = extractelement <16 x i1> [[TMP0]], i32 11 -; DEFAULT-NEXT: br i1 [[TMP52]], label %[[PRED_STORE_IF26:.*]], label %[[PRED_STORE_CONTINUE27:.*]] -; DEFAULT: [[PRED_STORE_IF26]]: -; DEFAULT-NEXT: [[TMP53:%.*]] = add i64 [[INDEX]], 11 -; DEFAULT-NEXT: [[TMP54:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP53]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE24]] +; DEFAULT: [[PRED_STORE_CONTINUE24]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF25:.*]], label %[[PRED_STORE_CONTINUE26:.*]] +; DEFAULT: [[PRED_STORE_IF25]]: +; DEFAULT-NEXT: [[TMP54:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 11 ; DEFAULT-NEXT: [[TMP55:%.*]] = extractelement <16 x i8> [[TMP7]], i32 11 ; DEFAULT-NEXT: store i8 [[TMP55]], ptr [[TMP54]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE27]] -; DEFAULT: [[PRED_STORE_CONTINUE27]]: -; DEFAULT-NEXT: [[TMP56:%.*]] = extractelement <16 x i1> [[TMP0]], i32 12 -; DEFAULT-NEXT: br i1 [[TMP56]], label %[[PRED_STORE_IF28:.*]], label %[[PRED_STORE_CONTINUE29:.*]] -; DEFAULT: [[PRED_STORE_IF28]]: -; DEFAULT-NEXT: [[TMP57:%.*]] = add i64 [[INDEX]], 12 -; DEFAULT-NEXT: [[TMP58:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP57]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE26]] +; DEFAULT: [[PRED_STORE_CONTINUE26]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF27:.*]], label %[[PRED_STORE_CONTINUE28:.*]] +; DEFAULT: [[PRED_STORE_IF27]]: +; DEFAULT-NEXT: [[TMP58:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 ; DEFAULT-NEXT: [[TMP59:%.*]] = extractelement <16 x i8> [[TMP7]], i32 12 ; DEFAULT-NEXT: store i8 [[TMP59]], ptr [[TMP58]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE29]] -; DEFAULT: [[PRED_STORE_CONTINUE29]]: -; DEFAULT-NEXT: [[TMP60:%.*]] = extractelement <16 x i1> [[TMP0]], i32 13 -; DEFAULT-NEXT: br i1 [[TMP60]], label %[[PRED_STORE_IF30:.*]], label %[[PRED_STORE_CONTINUE31:.*]] -; DEFAULT: [[PRED_STORE_IF30]]: -; DEFAULT-NEXT: [[TMP61:%.*]] = add i64 [[INDEX]], 13 -; DEFAULT-NEXT: [[TMP62:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP61]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE28]] +; DEFAULT: [[PRED_STORE_CONTINUE28]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF29:.*]], label %[[PRED_STORE_CONTINUE30:.*]] +; DEFAULT: [[PRED_STORE_IF29]]: +; DEFAULT-NEXT: [[TMP62:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 13 ; DEFAULT-NEXT: [[TMP63:%.*]] = extractelement <16 x i8> [[TMP7]], i32 13 ; DEFAULT-NEXT: store i8 [[TMP63]], ptr [[TMP62]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE31]] -; DEFAULT: [[PRED_STORE_CONTINUE31]]: -; DEFAULT-NEXT: [[TMP64:%.*]] = extractelement <16 x i1> [[TMP0]], i32 14 -; DEFAULT-NEXT: br i1 [[TMP64]], label %[[PRED_STORE_IF32:.*]], label %[[PRED_STORE_CONTINUE33:.*]] -; DEFAULT: [[PRED_STORE_IF32]]: -; DEFAULT-NEXT: [[TMP65:%.*]] = add i64 [[INDEX]], 14 -; DEFAULT-NEXT: [[TMP66:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP65]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE30]] +; DEFAULT: [[PRED_STORE_CONTINUE30]]: +; DEFAULT-NEXT: br i1 true, label %[[PRED_STORE_IF31:.*]], label %[[PRED_STORE_CONTINUE32:.*]] +; DEFAULT: [[PRED_STORE_IF31]]: +; DEFAULT-NEXT: [[TMP66:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 14 ; DEFAULT-NEXT: [[TMP67:%.*]] = extractelement <16 x i8> [[TMP7]], i32 14 ; DEFAULT-NEXT: store i8 [[TMP67]], ptr [[TMP66]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE33]] -; DEFAULT: [[PRED_STORE_CONTINUE33]]: -; DEFAULT-NEXT: [[TMP68:%.*]] = extractelement <16 x i1> [[TMP0]], i32 15 -; DEFAULT-NEXT: br i1 [[TMP68]], label %[[PRED_STORE_IF34:.*]], label %[[PRED_STORE_CONTINUE35]] -; DEFAULT: [[PRED_STORE_IF34]]: -; DEFAULT-NEXT: [[TMP69:%.*]] = add i64 [[INDEX]], 15 -; DEFAULT-NEXT: [[TMP70:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[TMP69]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE32]] +; DEFAULT: [[PRED_STORE_CONTINUE32]]: +; DEFAULT-NEXT: br i1 false, label %[[PRED_STORE_IF33:.*]], label %[[PRED_STORE_CONTINUE34:.*]] +; DEFAULT: [[PRED_STORE_IF33]]: +; DEFAULT-NEXT: [[TMP70:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 15 ; DEFAULT-NEXT: [[TMP71:%.*]] = extractelement <16 x i8> [[TMP7]], i32 15 ; DEFAULT-NEXT: store i8 [[TMP71]], ptr [[TMP70]], align 1 -; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE35]] -; DEFAULT: [[PRED_STORE_CONTINUE35]]: -; DEFAULT-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 -; DEFAULT-NEXT: [[VEC_IND_NEXT]] = add <16 x i8> [[VEC_IND]], splat (i8 16) -; DEFAULT-NEXT: [[VEC_IND_NEXT36]] = add <16 x i8> [[VEC_IND1]], splat (i8 16) -; DEFAULT-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; DEFAULT-NEXT: br label %[[PRED_STORE_CONTINUE34]] +; DEFAULT: [[PRED_STORE_CONTINUE34]]: +; DEFAULT-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; DEFAULT: [[MIDDLE_BLOCK]]: ; DEFAULT-NEXT: br label %[[FOR_COND_CLEANUP:.*]] ; DEFAULT: [[FOR_COND_CLEANUP]]: @@ -474,7 +433,7 @@ define void @sve_tail_predicate_without_minsize(ptr %p, i8 %a, i8 %b, i8 %c, i32 ; DEFAULT-NEXT: [[TMP24:%.*]] = extractelement [[ACTIVE_LANE_MASK_NEXT]], i32 0 ; DEFAULT-NEXT: [[TMP23:%.*]] = xor i1 [[TMP24]], true ; DEFAULT-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] -; DEFAULT-NEXT: br i1 [[TMP23]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; DEFAULT-NEXT: br i1 [[TMP23]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; DEFAULT: [[MIDDLE_BLOCK]]: ; DEFAULT-NEXT: br label %[[FOR_COND_CLEANUP:.*]] ; DEFAULT: [[FOR_COND_CLEANUP]]: @@ -630,7 +589,7 @@ define void @dont_vectorize_with_minsize() { ; DEFAULT-NEXT: store <8 x i16> [[TMP15]], ptr [[TMP11]], align 2 ; DEFAULT-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; DEFAULT-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 64 -; DEFAULT-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; DEFAULT-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] ; DEFAULT: [[MIDDLE_BLOCK]]: ; DEFAULT-NEXT: br label %[[FOR_COND_CLEANUP:.*]] ; DEFAULT: [[FOR_COND_CLEANUP]]: @@ -746,7 +705,7 @@ define void @vectorization_forced_minsize_reduce_width() { ; DEFAULT-NEXT: store <8 x i16> [[TMP15]], ptr [[TMP11]], align 2 ; DEFAULT-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; DEFAULT-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 64 -; DEFAULT-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] +; DEFAULT-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; DEFAULT: [[MIDDLE_BLOCK]]: ; DEFAULT-NEXT: br label %[[FOR_COND_CLEANUP:.*]] ; DEFAULT: [[FOR_COND_CLEANUP]]: diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs-apple.ll b/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs-apple.ll index a6d956ccac3d1..54e074add57c3 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs-apple.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs-apple.ll @@ -588,11 +588,7 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi double [ 3.000000e+00, %[[VECTOR_PH]] ], [ [[TMP21:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[IV:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr [[T:%.*]], ptr [[SRC_0]], i64 [[IV]] +; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr [[T:%.*]], ptr [[SRC_0]], i64 0 ; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <6 x double>, ptr [[GEP_0]], align 8 ; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <6 x double> [[WIDE_VEC]], <6 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <6 x double> [[WIDE_VEC]], <6 x double> poison, <2 x i32> @@ -602,11 +598,11 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK-NEXT: [[TMP5:%.*]] = fmul <2 x double> [[STRIDED_VEC2]], splat (double 3.000000e+00) ; CHECK-NEXT: [[TMP6:%.*]] = fadd <2 x double> [[TMP3]], [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = fadd <2 x double> [[TMP6]], [[TMP5]] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr double, ptr [[SRC_1]], i64 [[IV]] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr double, ptr [[SRC_1]], i64 0 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x double>, ptr [[GEP_SRC]], align 8 ; CHECK-NEXT: [[TMP9:%.*]] = fmul <2 x double> [[TMP7]], [[WIDE_LOAD]] -; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr [[T_2:%.*]], ptr [[SRC_2]], i64 [[IV]] -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[T_2]], ptr [[SRC_2]], i64 [[TMP1]] +; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr [[T_2:%.*]], ptr [[SRC_2]], i64 0 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[T_2]], ptr [[SRC_2]], i64 1 ; CHECK-NEXT: [[GEP_72:%.*]] = getelementptr i8, ptr [[GEP_SRC_2]], i64 72 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[TMP11]], i64 72 ; CHECK-NEXT: [[L_P_2:%.*]] = load ptr, ptr [[GEP_72]], align 8 @@ -616,9 +612,8 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x double> poison, double [[LV]], i32 0 ; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x double> [[TMP18]], double [[TMP17]], i32 1 ; CHECK-NEXT: [[TMP20:%.*]] = fmul <2 x double> [[TMP9]], [[TMP19]] -; CHECK-NEXT: [[TMP21]] = call double @llvm.vector.reduce.fadd.v2f64(double [[VEC_PHI]], <2 x double> [[TMP20]]) -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP21:![0-9]+]] +; CHECK-NEXT: [[TMP21:%.*]] = call double @llvm.vector.reduce.fadd.v2f64(double 3.000000e+00, <2 x double> [[TMP20]]) +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[EXIT]]: @@ -779,7 +774,7 @@ define i32 @test_or_reduction_with_stride_2(i32 %scale, ptr %src) { ; CHECK-NEXT: [[TMP66]] = or <16 x i32> [[TMP65]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP67:%.*]] = icmp eq i64 [[INDEX_NEXT]], 48 -; CHECK-NEXT: br i1 [[TMP67]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP67]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP21:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP68:%.*]] = call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> [[TMP66]]) ; CHECK-NEXT: br label %[[SCALAR_PH:.*]] diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs.ll b/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs.ll index b6ddf1d3e7a90..d1248a1ad1ac4 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/replicating-load-store-costs.ll @@ -552,11 +552,7 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi double [ 3.000000e+00, %[[VECTOR_PH]] ], [ [[TMP21:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[IV:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr [[T:%.*]], ptr [[SRC_0]], i64 [[IV]] +; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr [[T:%.*]], ptr [[SRC_0]], i64 0 ; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <6 x double>, ptr [[GEP_0]], align 8 ; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <6 x double> [[WIDE_VEC]], <6 x double> poison, <2 x i32> ; CHECK-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <6 x double> [[WIDE_VEC]], <6 x double> poison, <2 x i32> @@ -566,11 +562,11 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK-NEXT: [[TMP5:%.*]] = fmul <2 x double> [[STRIDED_VEC2]], splat (double 3.000000e+00) ; CHECK-NEXT: [[TMP6:%.*]] = fadd <2 x double> [[TMP3]], [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = fadd <2 x double> [[TMP6]], [[TMP5]] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr double, ptr [[SRC_1]], i64 [[IV]] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr double, ptr [[SRC_1]], i64 0 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x double>, ptr [[GEP_SRC]], align 8 ; CHECK-NEXT: [[TMP9:%.*]] = fmul <2 x double> [[TMP7]], [[WIDE_LOAD]] -; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr [[T_2:%.*]], ptr [[SRC_2]], i64 [[IV]] -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[T_2]], ptr [[SRC_2]], i64 [[TMP1]] +; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr [[T_2:%.*]], ptr [[SRC_2]], i64 0 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[T_2]], ptr [[SRC_2]], i64 1 ; CHECK-NEXT: [[GEP_72:%.*]] = getelementptr i8, ptr [[GEP_SRC_2]], i64 72 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[TMP11]], i64 72 ; CHECK-NEXT: [[L_P_2:%.*]] = load ptr, ptr [[GEP_72]], align 8 @@ -580,9 +576,8 @@ define double @test_scalarization_cost_for_load_of_address(ptr %src.0, ptr %src. ; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x double> poison, double [[LV]], i32 0 ; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x double> [[TMP18]], double [[TMP17]], i32 1 ; CHECK-NEXT: [[TMP20:%.*]] = fmul <2 x double> [[TMP9]], [[TMP19]] -; CHECK-NEXT: [[TMP21]] = call double @llvm.vector.reduce.fadd.v2f64(double [[VEC_PHI]], <2 x double> [[TMP20]]) -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP21:![0-9]+]] +; CHECK-NEXT: [[TMP21:%.*]] = call double @llvm.vector.reduce.fadd.v2f64(double 3.000000e+00, <2 x double> [[TMP20]]) +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[EXIT]]: @@ -743,7 +738,7 @@ define i32 @test_or_reduction_with_stride_2(i32 %scale, ptr %src) { ; CHECK-NEXT: [[TMP66]] = or <16 x i32> [[TMP65]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP67:%.*]] = icmp eq i64 [[INDEX_NEXT]], 48 -; CHECK-NEXT: br i1 [[TMP67]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP67]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP21:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP68:%.*]] = call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> [[TMP66]]) ; CHECK-NEXT: br label %[[SCALAR_PH:.*]] diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/low-trip-count.ll b/llvm/test/Transforms/LoopVectorize/RISCV/low-trip-count.ll index 78b54efe7e682..0af9795cfdf62 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/low-trip-count.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/low-trip-count.ll @@ -285,13 +285,9 @@ define i8 @mul_non_pow_2_low_trip_count(ptr noalias %a) { ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i8> [ , [[VECTOR_PH]] ], [ [[TMP1:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP0]], align 1 -; CHECK-NEXT: [[TMP1]] = mul <8 x i8> [[WIDE_LOAD]], [[VEC_PHI]] -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP0:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = mul <8 x i8> [[WIDE_LOAD]], +; CHECK-NEXT: br label [[MIDDLE_BLOCK:%.*]] ; CHECK: middle.block: ; CHECK-NEXT: [[TMP3:%.*]] = call i8 @llvm.vector.reduce.mul.v8i8(<8 x i8> [[TMP1]]) ; CHECK-NEXT: br label [[SCALAR_PH:%.*]] @@ -300,12 +296,12 @@ define i8 @mul_non_pow_2_low_trip_count(ptr noalias %a) { ; CHECK: for.body: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 8, [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ] ; CHECK-NEXT: [[RDX:%.*]] = phi i8 [ [[TMP3]], [[SCALAR_PH]] ], [ [[MUL:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 [[IV]] ; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[GEP]], align 1 ; CHECK-NEXT: [[MUL]] = mul i8 [[TMP5]], [[RDX]] ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 10 -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: for.end: ; CHECK-NEXT: [[MUL_LCSSA:%.*]] = phi i8 [ [[MUL]], [[FOR_BODY]] ] ; CHECK-NEXT: ret i8 [[MUL_LCSSA]] diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/vector-loop-backedge-elimination-with-evl.ll b/llvm/test/Transforms/LoopVectorize/RISCV/vector-loop-backedge-elimination-with-evl.ll index f1dda3d5a2f91..a80d5dacff583 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/vector-loop-backedge-elimination-with-evl.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/vector-loop-backedge-elimination-with-evl.ll @@ -41,13 +41,9 @@ define i32 @test_remove_iv(i32 %start) #0 { ; CHECK-NEXT: [[TMP2:%.*]] = insertelement zeroinitializer, i32 [[START]], i32 0 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi [ [[TMP2]], %[[VECTOR_PH]] ], [ [[TMP5:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[AVL:%.*]] = phi i32 [ 6, %[[VECTOR_PH]] ], [ [[AVL_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.experimental.get.vector.length.i32(i32 [[AVL]], i32 4, i1 true) -; CHECK-NEXT: [[TMP4:%.*]] = xor [[VEC_PHI]], splat (i32 3) -; CHECK-NEXT: [[TMP5]] = call @llvm.vp.merge.nxv4i32( splat (i1 true), [[TMP4]], [[VEC_PHI]], i32 [[TMP3]]) -; CHECK-NEXT: [[AVL_NEXT]] = sub nuw i32 [[AVL]], [[TMP3]] -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[TMP3:%.*]] = xor [[TMP2]], splat (i32 3) +; CHECK-NEXT: [[TMP5:%.*]] = call @llvm.vp.merge.nxv4i32( splat (i1 true), [[TMP3]], [[TMP2]], i32 6) +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.xor.nxv4i32( [[TMP5]]) ; CHECK-NEXT: br label %[[EXIT:.*]] @@ -71,8 +67,3 @@ exit: attributes #0 = { vscale_range(2,2) } -;. -; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} -; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} -;. diff --git a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll index 1bd308855b9ea..c96c40b81f990 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll @@ -606,19 +606,19 @@ define i64 @live_in_known_1_via_scev() { ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, %[[ENTRY]] ] ; CHECK-NEXT: [[N:%.*]] = add nuw nsw i32 [[SEL]], 6 ; CHECK-NEXT: [[P_EXT:%.*]] = zext nneg i32 [[P]] to i64 -; CHECK-NEXT: br label %[[VECTOR_PH:.*]] -; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ , %[[VECTOR_PH]] ], [ [[VEC_PHI]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_BODY]] ], [ [[INDEX_NEXT:%.*]], %[[EXIT]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ , %[[VECTOR_BODY]] ], [ [[VEC_PHI]], %[[EXIT]] ] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[INDEX_NEXT]], 8 -; CHECK-NEXT: br i1 [[TMP0]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP0]], label %[[MIDDLE_BLOCK:.*]], label %[[EXIT]], !llvm.loop [[LOOP22:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vector.reduce.mul.v4i64(<4 x i64> [[VEC_PHI]]) -; CHECK-NEXT: br label %[[EXIT:.*]] -; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: ; CHECK-NEXT: ret i64 [[TMP3]] ; entry: @@ -660,9 +660,8 @@ define i64 @cost_loop_invariant_recipes(i1 %x, i64 %y) { ; CHECK-NEXT: [[TMP2:%.*]] = shl <2 x i64> [[BROADCAST_SPLAT]], [[TMP1]] ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ splat (i64 1), %[[VECTOR_PH]] ], [ [[TMP3:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3]] = mul <2 x i64> [[TMP2]], [[VEC_PHI]] -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP23:![0-9]+]] +; CHECK-NEXT: [[TMP3:%.*]] = mul <2 x i64> [[TMP2]], splat (i64 1) +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vector.reduce.mul.v2i64(<2 x i64> [[TMP3]]) ; CHECK-NEXT: br label %[[EXIT:.*]] @@ -700,18 +699,15 @@ define i32 @narrowed_reduction(ptr %a, i1 %cmp) #0 { ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <16 x i32> [[BROADCAST_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i32> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP3:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP0:%.*]] = and <16 x i32> [[VEC_PHI]], splat (i32 1) -; CHECK-NEXT: [[TMP1:%.*]] = or <16 x i32> [[TMP0]], [[BROADCAST_SPLAT]] -; CHECK-NEXT: [[TMP2:%.*]] = trunc <16 x i32> [[TMP1]] to <16 x i1> -; CHECK-NEXT: [[TMP3]] = zext <16 x i1> [[TMP2]] to <16 x i32> -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = or <16 x i32> zeroinitializer, [[BROADCAST_SPLAT]] +; CHECK-NEXT: [[TMP1:%.*]] = trunc <16 x i32> [[TMP0]] to <16 x i1> +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[TMP2]]) -; CHECK-NEXT: [[TMP5:%.*]] = zext i1 [[TMP4]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[TMP1]]) +; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: ret i32 [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP3]] ; entry: %conv = zext i1 %cmp to i32 @@ -781,7 +777,7 @@ define i32 @g(i64 %n) { ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 16 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i32> [[STEP_ADD_3]], splat (i32 4) ; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP19]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP25:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP19]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP23:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[BIN_RDX:%.*]] = or <4 x i32> [[TMP16]], [[TMP15]] ; CHECK-NEXT: [[BIN_RDX5:%.*]] = or <4 x i32> [[TMP17]], [[BIN_RDX]] @@ -815,7 +811,7 @@ define i32 @g(i64 %n) { ; CHECK-NEXT: [[INDEX_NEXT15]] = add nuw i32 [[INDEX9]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT11]] = add <4 x i32> [[VEC_IND10]], splat (i32 4) ; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i32 [[INDEX_NEXT15]], [[N_VEC8]] -; CHECK-NEXT: br i1 [[TMP26]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP26]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] ; CHECK: [[VEC_EPILOG_MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP27:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP25]]) ; CHECK-NEXT: [[CMP_N18:%.*]] = icmp eq i32 [[TMP1]], [[N_VEC8]] diff --git a/llvm/test/Transforms/LoopVectorize/X86/load-deref-pred.ll b/llvm/test/Transforms/LoopVectorize/X86/load-deref-pred.ll index 934dd3eccb9b2..654414b5c3fac 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/load-deref-pred.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/load-deref-pred.ll @@ -2454,44 +2454,22 @@ define i32 @test_non_unit_stride_five(i64 %len, ptr %test_base) { ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP112:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP113:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP114:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI3:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP115:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 5 -; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[OFFSET_IDX]], 5 -; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[OFFSET_IDX]], 10 -; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[OFFSET_IDX]], 15 -; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[OFFSET_IDX]], 20 -; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], 25 -; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 30 -; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[OFFSET_IDX]], 35 -; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[OFFSET_IDX]], 40 -; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[OFFSET_IDX]], 45 -; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[OFFSET_IDX]], 50 -; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[OFFSET_IDX]], 55 -; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[OFFSET_IDX]], 60 -; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[OFFSET_IDX]], 65 -; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[OFFSET_IDX]], 70 -; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[OFFSET_IDX]], 75 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE:%.*]], i64 [[TMP0]] -; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP1]] -; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP2]] -; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP3]] -; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP9]] -; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP10]] -; CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP11]] -; CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP13]] -; CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP14]] -; CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE:%.*]], i64 0 +; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 5 +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 10 +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 15 +; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 20 +; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 25 +; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 30 +; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 35 +; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 40 +; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 45 +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 50 +; CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 55 +; CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 60 +; CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 65 +; CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 70 +; CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds i1, ptr [[TEST_BASE]], i64 75 ; CHECK-NEXT: [[TMP32:%.*]] = load i1, ptr [[TMP16]], align 1 ; CHECK-NEXT: [[TMP33:%.*]] = load i1, ptr [[TMP17]], align 1 ; CHECK-NEXT: [[TMP34:%.*]] = load i1, ptr [[TMP18]], align 1 @@ -2524,22 +2502,22 @@ define i32 @test_non_unit_stride_five(i64 %len, ptr %test_base) { ; CHECK-NEXT: [[TMP61:%.*]] = insertelement <4 x i1> [[TMP60]], i1 [[TMP57]], i32 1 ; CHECK-NEXT: [[TMP62:%.*]] = insertelement <4 x i1> [[TMP61]], i1 [[TMP58]], i32 2 ; CHECK-NEXT: [[TMP63:%.*]] = insertelement <4 x i1> [[TMP62]], i1 [[TMP59]], i32 3 -; CHECK-NEXT: [[TMP64:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP0]] -; CHECK-NEXT: [[TMP65:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP1]] -; CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP2]] -; CHECK-NEXT: [[TMP67:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP3]] -; CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP71:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP72:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP73:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP9]] -; CHECK-NEXT: [[TMP74:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP10]] -; CHECK-NEXT: [[TMP75:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP11]] -; CHECK-NEXT: [[TMP76:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP77:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP13]] -; CHECK-NEXT: [[TMP78:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP14]] -; CHECK-NEXT: [[TMP79:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP64:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 0 +; CHECK-NEXT: [[TMP65:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 5 +; CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 10 +; CHECK-NEXT: [[TMP67:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 15 +; CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 20 +; CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 25 +; CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 30 +; CHECK-NEXT: [[TMP71:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 35 +; CHECK-NEXT: [[TMP72:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 40 +; CHECK-NEXT: [[TMP73:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 45 +; CHECK-NEXT: [[TMP74:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 50 +; CHECK-NEXT: [[TMP75:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 55 +; CHECK-NEXT: [[TMP76:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 60 +; CHECK-NEXT: [[TMP77:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 65 +; CHECK-NEXT: [[TMP78:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 70 +; CHECK-NEXT: [[TMP79:%.*]] = getelementptr inbounds i32, ptr [[ALLOCA]], i64 75 ; CHECK-NEXT: [[TMP80:%.*]] = load i32, ptr [[TMP64]], align 4 ; CHECK-NEXT: [[TMP81:%.*]] = load i32, ptr [[TMP65]], align 4 ; CHECK-NEXT: [[TMP82:%.*]] = load i32, ptr [[TMP66]], align 4 @@ -2576,16 +2554,12 @@ define i32 @test_non_unit_stride_five(i64 %len, ptr %test_base) { ; CHECK-NEXT: [[PREDPHI4:%.*]] = select <4 x i1> [[TMP47]], <4 x i32> [[TMP95]], <4 x i32> zeroinitializer ; CHECK-NEXT: [[PREDPHI5:%.*]] = select <4 x i1> [[TMP55]], <4 x i32> [[TMP103]], <4 x i32> zeroinitializer ; CHECK-NEXT: [[PREDPHI6:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP111]], <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP112]] = add <4 x i32> [[VEC_PHI]], [[PREDPHI]] -; CHECK-NEXT: [[TMP113]] = add <4 x i32> [[VEC_PHI1]], [[PREDPHI4]] -; CHECK-NEXT: [[TMP114]] = add <4 x i32> [[VEC_PHI2]], [[PREDPHI5]] -; CHECK-NEXT: [[TMP115]] = add <4 x i32> [[VEC_PHI3]], [[PREDPHI6]] -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 -; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] +; CHECK-NEXT: [[TMP112:%.*]] = add <4 x i32> zeroinitializer, [[PREDPHI]] +; CHECK-NEXT: br label [[MIDDLE_BLOCK:%.*]] ; CHECK: middle.block: -; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP113]], [[TMP112]] -; CHECK-NEXT: [[BIN_RDX7:%.*]] = add <4 x i32> [[TMP114]], [[BIN_RDX]] -; CHECK-NEXT: [[BIN_RDX8:%.*]] = add <4 x i32> [[TMP115]], [[BIN_RDX7]] +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[PREDPHI4]], [[TMP112]] +; CHECK-NEXT: [[BIN_RDX4:%.*]] = add <4 x i32> [[PREDPHI5]], [[BIN_RDX]] +; CHECK-NEXT: [[BIN_RDX8:%.*]] = add <4 x i32> [[PREDPHI6]], [[BIN_RDX4]] ; CHECK-NEXT: [[TMP117:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX8]]) ; CHECK-NEXT: br label [[SCALAR_PH:%.*]] ; CHECK: scalar.ph: @@ -2605,7 +2579,7 @@ define i32 @test_non_unit_stride_five(i64 %len, ptr %test_base) { ; CHECK-NEXT: [[VAL_PHI:%.*]] = phi i32 [ 0, [[LOOP]] ], [ [[VAL]], [[PRED]] ] ; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[VAL_PHI]] ; CHECK-NEXT: [[EXIT:%.*]] = icmp ugt i64 [[IV]], 100 -; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP23:![0-9]+]] +; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP22:![0-9]+]] ; CHECK: loop_exit: ; CHECK-NEXT: [[ACCUM_NEXT_LCSSA:%.*]] = phi i32 [ [[ACCUM_NEXT]], [[LATCH]] ] ; CHECK-NEXT: ret i32 [[ACCUM_NEXT_LCSSA]] @@ -2772,7 +2746,7 @@ define i32 @test_non_unit_stride_off_by_four_bytes(i64 %len, ptr %test_base) { ; CHECK-NEXT: [[TMP115]] = add <4 x i32> [[VEC_PHI3]], [[PREDPHI6]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP116:%.*]] = icmp eq i64 [[INDEX_NEXT]], 48 -; CHECK-NEXT: br i1 [[TMP116]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP116]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP23:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP113]], [[TMP112]] ; CHECK-NEXT: [[BIN_RDX7:%.*]] = add <4 x i32> [[TMP114]], [[BIN_RDX]] @@ -2796,7 +2770,7 @@ define i32 @test_non_unit_stride_off_by_four_bytes(i64 %len, ptr %test_base) { ; CHECK-NEXT: [[VAL_PHI:%.*]] = phi i32 [ 0, [[LOOP]] ], [ [[VAL]], [[PRED]] ] ; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[VAL_PHI]] ; CHECK-NEXT: [[EXIT:%.*]] = icmp ugt i64 [[IV]], 100 -; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP25:![0-9]+]] +; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP24:![0-9]+]] ; CHECK: loop_exit: ; CHECK-NEXT: [[ACCUM_NEXT_LCSSA:%.*]] = phi i32 [ [[ACCUM_NEXT]], [[LATCH]] ] ; CHECK-NEXT: ret i32 [[ACCUM_NEXT_LCSSA]] @@ -2980,7 +2954,7 @@ define i32 @test_non_unit_stride_with_first_iteration_step_access(i64 %len, ptr ; CHECK-NEXT: [[TMP131]] = add <4 x i32> [[VEC_PHI3]], [[PREDPHI6]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP132:%.*]] = icmp eq i64 [[INDEX_NEXT]], 144 -; CHECK-NEXT: br i1 [[TMP132]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP132]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP25:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP129]], [[TMP128]] ; CHECK-NEXT: [[BIN_RDX7:%.*]] = add <4 x i32> [[TMP130]], [[BIN_RDX]] @@ -3004,7 +2978,7 @@ define i32 @test_non_unit_stride_with_first_iteration_step_access(i64 %len, ptr ; CHECK-NEXT: [[VAL_PHI:%.*]] = phi i32 [ 0, [[LOOP]] ], [ [[VAL]], [[PRED]] ] ; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[VAL_PHI]] ; CHECK-NEXT: [[EXIT:%.*]] = icmp ugt i64 [[IV]], 300 -; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP27:![0-9]+]] +; CHECK-NEXT: br i1 [[EXIT]], label [[LOOP_EXIT:%.*]], label [[LOOP]], !llvm.loop [[LOOP26:![0-9]+]] ; CHECK: loop_exit: ; CHECK-NEXT: [[ACCUM_NEXT_LCSSA:%.*]] = phi i32 [ [[ACCUM_NEXT]], [[LATCH]] ] ; CHECK-NEXT: ret i32 [[ACCUM_NEXT_LCSSA]] diff --git a/llvm/test/Transforms/LoopVectorize/epilog-vectorization-reductions.ll b/llvm/test/Transforms/LoopVectorize/epilog-vectorization-reductions.ll index 76f30decf81e7..4a3356889c36e 100644 --- a/llvm/test/Transforms/LoopVectorize/epilog-vectorization-reductions.ll +++ b/llvm/test/Transforms/LoopVectorize/epilog-vectorization-reductions.ll @@ -777,10 +777,9 @@ define i16 @test_no_op_or_reduction_single_vector_iteration(i64 %N) { ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[CLAMPED]], [[N_MOD_VF]] ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i16> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[VEC_PHI]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP27:![0-9]+]] +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[VEC_PHI]]) +; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> zeroinitializer) ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[CLAMPED]], [[N_VEC]] ; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[VEC_EPILOG_ITER_CHECK:.*]] ; CHECK: [[VEC_EPILOG_ITER_CHECK]]: @@ -794,23 +793,22 @@ define i16 @test_no_op_or_reduction_single_vector_iteration(i64 %N) { ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> zeroinitializer, i16 [[BC_MERGE_RDX]], i32 0 ; CHECK-NEXT: br label %[[VEC_EPILOG_VECTOR_BODY:.*]] ; CHECK: [[VEC_EPILOG_VECTOR_BODY]]: -; CHECK-NEXT: [[VEC_PHI4:%.*]] = phi <4 x i16> [ [[TMP1]], %[[VEC_EPILOG_PH]] ], [ [[VEC_PHI4]], %[[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-NEXT: br i1 true, label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] +; CHECK-NEXT: br label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]] ; CHECK: [[VEC_EPILOG_MIDDLE_BLOCK]]: -; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[VEC_PHI4]]) +; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[TMP1]]) ; CHECK-NEXT: [[CMP_N5:%.*]] = icmp eq i64 [[CLAMPED]], [[N_VEC3]] ; CHECK-NEXT: br i1 [[CMP_N5]], label %[[EXIT]], label %[[VEC_EPILOG_SCALAR_PH]] ; CHECK: [[VEC_EPILOG_SCALAR_PH]]: ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC3]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] -; CHECK-NEXT: [[BC_MERGE_RDX6:%.*]] = phi i16 [ [[TMP2]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[TMP0]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_MERGE_RDX5:%.*]] = phi i16 [ [[TMP2]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[TMP0]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[RED:%.*]] = phi i16 [ [[BC_MERGE_RDX6]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[RED_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[RED:%.*]] = phi i16 [ [[BC_MERGE_RDX5]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[RED_NEXT:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[RED_NEXT]] = or i16 [[RED]], 0 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[CLAMPED]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP29:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP27:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[RED_NEXT_LCSSA:%.*]] = phi i16 [ [[RED_NEXT]], %[[LOOP]] ], [ [[TMP0]], %[[MIDDLE_BLOCK]] ], [ [[TMP2]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i16 [[RED_NEXT_LCSSA]] @@ -830,3 +828,183 @@ loop: exit: ret i16 %red.next } + +; Test or-reduction with an induction-derived operand and a small bounded trip +; count. The main vector loop is dissolved (trip count <= VF), and the epilogue +; vector loop's reduction body remains with a ReductionStartVector operand. +define i16 @test_or_reduction_with_induction_single_vector_iteration(i64 %N) { +; CHECK-LABEL: define i16 @test_or_reduction_with_induction_single_vector_iteration( +; CHECK-SAME: i64 [[N:%.*]]) { +; CHECK-NEXT: [[ITER_CHECK:.*]]: +; CHECK-NEXT: [[CLAMPED:%.*]] = call i64 @llvm.umin.i64(i64 [[N]], i64 4) +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[CLAMPED]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VECTOR_MAIN_LOOP_ITER_CHECK:.*]] +; CHECK: [[VECTOR_MAIN_LOOP_ITER_CHECK]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK1:%.*]] = icmp ult i64 [[CLAMPED]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK1]], label %[[VEC_EPILOG_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[CLAMPED]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[CLAMPED]], [[N_MOD_VF]] +; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[N_VEC]] to i32 +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> ) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[CLAMPED]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[VEC_EPILOG_ITER_CHECK:.*]] +; CHECK: [[VEC_EPILOG_ITER_CHECK]]: +; CHECK-NEXT: [[IND_END:%.*]] = trunc i64 [[N_VEC]] to i32 +; CHECK-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_MOD_VF]], 4 +; CHECK-NEXT: br i1 [[MIN_EPILOG_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH]], label %[[VEC_EPILOG_PH]], !prof [[PROF3]] +; CHECK: [[VEC_EPILOG_PH]]: +; CHECK-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[TMP0]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i16 [ [[TMP1]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; CHECK-NEXT: [[N_MOD_VF2:%.*]] = urem i64 [[CLAMPED]], 4 +; CHECK-NEXT: [[N_VEC3:%.*]] = sub i64 [[CLAMPED]], [[N_MOD_VF2]] +; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[N_VEC3]] to i32 +; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i16> zeroinitializer, i16 [[BC_MERGE_RDX]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[BC_RESUME_VAL]] to i16 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[TMP4]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[INDUCTION:%.*]] = add <4 x i16> [[BROADCAST_SPLAT]], +; CHECK-NEXT: br label %[[VEC_EPILOG_VECTOR_BODY:.*]] +; CHECK: [[VEC_EPILOG_VECTOR_BODY]]: +; CHECK-NEXT: [[TMP5:%.*]] = or <4 x i16> [[TMP3]], [[INDUCTION]] +; CHECK-NEXT: br label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]] +; CHECK: [[VEC_EPILOG_MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP6:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[TMP5]]) +; CHECK-NEXT: [[CMP_N4:%.*]] = icmp eq i64 [[CLAMPED]], [[N_VEC3]] +; CHECK-NEXT: br i1 [[CMP_N4]], label %[[EXIT]], label %[[VEC_EPILOG_SCALAR_PH]] +; CHECK: [[VEC_EPILOG_SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL5:%.*]] = phi i64 [ [[N_VEC3]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL6:%.*]] = phi i32 [ [[TMP2]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_MERGE_RDX7:%.*]] = phi i16 [ [[TMP6]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[TMP1]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL5]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[SHIFT:%.*]] = phi i32 [ [[BC_RESUME_VAL6]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[SHIFT_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[RED:%.*]] = phi i16 [ [[BC_MERGE_RDX7]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[RED_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SHIFT]] to i16 +; CHECK-NEXT: [[RED_NEXT]] = or i16 [[RED]], [[TRUNC]] +; CHECK-NEXT: [[SHIFT_NEXT]] = add i32 [[SHIFT]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[CLAMPED]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP28:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[RED_NEXT_LCSSA:%.*]] = phi i16 [ [[RED_NEXT]], %[[LOOP]] ], [ [[TMP1]], %[[MIDDLE_BLOCK]] ], [ [[TMP6]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret i16 [[RED_NEXT_LCSSA]] +; +entry: + %clamped = call i64 @llvm.umin.i32(i64 %N, i64 4) + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %shift = phi i32 [ 0, %entry ], [ %shift.next, %loop ] + %red = phi i16 [ 0, %entry ], [ %red.next, %loop ] + %trunc = trunc i32 %shift to i16 + %red.next = or i16 %red, %trunc + %shift.next = add i32 %shift, 1 + %iv.next = add i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %clamped + br i1 %ec, label %exit, label %loop + +exit: + ret i16 %red.next +} + +; Test AnyOf reduction in epilogue with a small trip count that results in +; the epilogue vector loop being dissolved (single iteration). +define i32 @anyof_reduction_in_dissolved_epilogue(i32 %val, i1 %c) { +; CHECK-LABEL: define i32 @anyof_reduction_in_dissolved_epilogue( +; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[START:%.*]] = sext i1 [[C]] to i32 +; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[C]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[START]] +; CHECK-NEXT: br label %[[ITER_CHECK:.*]] +; CHECK: [[OUTER_HEADER_LOOPEXIT:.*]]: +; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i32 [ [[SEL:%.*]], %[[LOOP:.*]] ], [ [[RDX_SELECT:%.*]], %[[MIDDLE_BLOCK:.*]] ], [ [[RDX_SELECT7:%.*]], %[[VEC_EPILOG_MIDDLE_BLOCK:.*]] ] +; CHECK-NEXT: br label %[[ITER_CHECK]] +; CHECK: [[ITER_CHECK]]: +; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[SEL_LCSSA]], %[[OUTER_HEADER_LOOPEXIT]] ] +; CHECK-NEXT: br i1 true, label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VECTOR_MAIN_LOOP_ITER_CHECK:.*]] +; CHECK: [[VECTOR_MAIN_LOOP_ITER_CHECK]]: +; CHECK-NEXT: br i1 true, label %[[VEC_EPILOG_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP1]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP1]], [[N_MOD_VF]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[VAL]], 0 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP2]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: br label %[[MIDDLE_BLOCK]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[BROADCAST_SPLAT]]) +; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] +; CHECK-NEXT: [[RDX_SELECT]] = select i1 [[TMP4]], i32 [[OUTER_IV]], i32 0 +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP1]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label %[[OUTER_HEADER_LOOPEXIT]], label %[[VEC_EPILOG_ITER_CHECK:.*]] +; CHECK: [[VEC_EPILOG_ITER_CHECK]]: +; CHECK-NEXT: [[IND_END:%.*]] = add i32 [[START]], [[N_VEC]] +; CHECK-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i32 [[N_MOD_VF]], 4 +; CHECK-NEXT: br i1 [[MIN_EPILOG_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH]], label %[[VEC_EPILOG_PH]], !prof [[PROF3]] +; CHECK: [[VEC_EPILOG_PH]]: +; CHECK-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[RDX_SELECT]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[BC_MERGE_RDX]], 0 +; CHECK-NEXT: [[N_MOD_VF1:%.*]] = urem i32 [[TMP1]], 4 +; CHECK-NEXT: [[N_VEC2:%.*]] = sub i32 [[TMP1]], [[N_MOD_VF1]] +; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[START]], [[N_VEC2]] +; CHECK-NEXT: [[TMP7:%.*]] = icmp ne i32 [[VAL]], 0 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i1> poison, i1 [[TMP7]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT5]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x i1> poison, i1 [[TMP5]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT3]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: br label %[[VEC_EPILOG_VECTOR_BODY:.*]] +; CHECK: [[VEC_EPILOG_VECTOR_BODY]]: +; CHECK-NEXT: [[TMP8:%.*]] = or <4 x i1> [[BROADCAST_SPLAT4]], [[BROADCAST_SPLAT6]] +; CHECK-NEXT: br label %[[VEC_EPILOG_MIDDLE_BLOCK]] +; CHECK: [[VEC_EPILOG_MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP9:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP8]]) +; CHECK-NEXT: [[TMP10:%.*]] = freeze i1 [[TMP9]] +; CHECK-NEXT: [[RDX_SELECT7]] = select i1 [[TMP10]], i32 [[OUTER_IV]], i32 0 +; CHECK-NEXT: [[CMP_N8:%.*]] = icmp eq i32 [[TMP1]], [[N_VEC2]] +; CHECK-NEXT: br i1 [[CMP_N8]], label %[[OUTER_HEADER_LOOPEXIT]], label %[[VEC_EPILOG_SCALAR_PH]] +; CHECK: [[VEC_EPILOG_SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[TMP6]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END]], %[[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], %[[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_MERGE_RDX9:%.*]] = phi i32 [ [[RDX_SELECT7]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[RDX_SELECT]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ] +; CHECK-NEXT: br label %[[LOOP]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[RDX:%.*]] = phi i32 [ [[BC_MERGE_RDX9]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[SEL]], %[[LOOP]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 0 +; CHECK-NEXT: [[SEL]] = select i1 [[CMP]], i32 [[RDX]], i32 [[OUTER_IV]] +; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 +; CHECK-NEXT: [[TC:%.*]] = zext i1 [[C]] to i32 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV_NEXT]], [[TC]] +; CHECK-NEXT: br i1 [[EC]], label %[[OUTER_HEADER_LOOPEXIT]], label %[[LOOP]], !llvm.loop [[LOOP29:![0-9]+]] +; +entry: + %start = sext i1 %c to i32 + br label %outer.header + +outer.header: + %outer.iv = phi i32 [ 0, %entry ], [ %sel, %loop ] + br label %loop + +loop: + %iv = phi i32 [ %start, %outer.header ], [ %iv.next, %loop ] + %rdx = phi i32 [ 0, %outer.header ], [ %sel, %loop ] + %cmp = icmp eq i32 %val, 0 + %sel = select i1 %cmp, i32 %rdx, i32 %outer.iv + %iv.next = add i32 %iv, 1 + %tc = zext i1 %c to i32 + %ec = icmp eq i32 %iv.next, %tc + br i1 %ec, label %outer.header, label %loop + + uselistorder i32 %sel, { 1, 0 } +} diff --git a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll index dd3ad4d01b465..b1027a8540c57 100644 --- a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll +++ b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll @@ -194,182 +194,129 @@ define i16 @select_decreasing_induction_icmp_table_i16(i16 noundef %val) { ; IC4VF4-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer ; IC4VF4-NEXT: br label %[[VECTOR_BODY:.*]] ; IC4VF4: [[VECTOR_BODY]]: -; IC4VF4-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE44:.*]] ] -; IC4VF4-NEXT: [[VEC_IND:%.*]] = phi <4 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP108:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI1:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP109:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP110:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI3:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP111:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[STEP_ADD:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 -4) -; IC4VF4-NEXT: [[STEP_ADD_2:%.*]] = add <4 x i16> [[STEP_ADD]], splat (i16 -4) -; IC4VF4-NEXT: [[STEP_ADD_3:%.*]] = add <4 x i16> [[STEP_ADD_2]], splat (i16 -4) -; IC4VF4-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; IC4VF4-NEXT: [[OFFSET_IDX:%.*]] = sub i16 12, [[DOTCAST]] -; IC4VF4-NEXT: [[BROADCAST_SPLATINSERT4:%.*]] = insertelement <4 x i32> poison, i32 [[INDEX]], i64 0 -; IC4VF4-NEXT: [[BROADCAST_SPLAT5:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT4]], <4 x i32> poison, <4 x i32> zeroinitializer -; IC4VF4-NEXT: [[VEC_IV:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV8:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV11:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV14:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[TMP0:%.*]] = icmp ule <4 x i32> [[VEC_IV]], splat (i32 11) -; IC4VF4-NEXT: [[TMP1:%.*]] = icmp ule <4 x i32> [[VEC_IV8]], splat (i32 11) -; IC4VF4-NEXT: [[TMP2:%.*]] = icmp ule <4 x i32> [[VEC_IV11]], splat (i32 11) -; IC4VF4-NEXT: [[TMP3:%.*]] = icmp ule <4 x i32> [[VEC_IV14]], splat (i32 11) -; IC4VF4-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP0]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP4]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] ; IC4VF4: [[PRED_LOAD_IF]]: -; IC4VF4-NEXT: [[TMP5:%.*]] = add i16 [[OFFSET_IDX]], 0 -; IC4VF4-NEXT: [[TMP6:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP5]] +; IC4VF4-NEXT: [[TMP6:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 12 ; IC4VF4-NEXT: [[TMP7:%.*]] = load i16, ptr [[TMP6]], align 1 ; IC4VF4-NEXT: [[TMP8:%.*]] = insertelement <4 x i16> poison, i16 [[TMP7]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE]] ; IC4VF4: [[PRED_LOAD_CONTINUE]]: ; IC4VF4-NEXT: [[TMP9:%.*]] = phi <4 x i16> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ] -; IC4VF4-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP0]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP10]], label %[[PRED_LOAD_IF15:.*]], label %[[PRED_LOAD_CONTINUE16:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF15:.*]], label %[[PRED_LOAD_CONTINUE16:.*]] ; IC4VF4: [[PRED_LOAD_IF15]]: -; IC4VF4-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], -1 -; IC4VF4-NEXT: [[TMP12:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP11]] +; IC4VF4-NEXT: [[TMP12:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 11 ; IC4VF4-NEXT: [[TMP13:%.*]] = load i16, ptr [[TMP12]], align 1 ; IC4VF4-NEXT: [[TMP14:%.*]] = insertelement <4 x i16> [[TMP9]], i16 [[TMP13]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE16]] ; IC4VF4: [[PRED_LOAD_CONTINUE16]]: ; IC4VF4-NEXT: [[TMP15:%.*]] = phi <4 x i16> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF15]] ] -; IC4VF4-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP0]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP16]], label %[[PRED_LOAD_IF17:.*]], label %[[PRED_LOAD_CONTINUE18:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF17:.*]], label %[[PRED_LOAD_CONTINUE18:.*]] ; IC4VF4: [[PRED_LOAD_IF17]]: -; IC4VF4-NEXT: [[TMP17:%.*]] = add i16 [[OFFSET_IDX]], -2 -; IC4VF4-NEXT: [[TMP18:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP17]] +; IC4VF4-NEXT: [[TMP18:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 10 ; IC4VF4-NEXT: [[TMP19:%.*]] = load i16, ptr [[TMP18]], align 1 ; IC4VF4-NEXT: [[TMP20:%.*]] = insertelement <4 x i16> [[TMP15]], i16 [[TMP19]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE18]] ; IC4VF4: [[PRED_LOAD_CONTINUE18]]: ; IC4VF4-NEXT: [[TMP21:%.*]] = phi <4 x i16> [ [[TMP15]], %[[PRED_LOAD_CONTINUE16]] ], [ [[TMP20]], %[[PRED_LOAD_IF17]] ] -; IC4VF4-NEXT: [[TMP22:%.*]] = extractelement <4 x i1> [[TMP0]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP22]], label %[[PRED_LOAD_IF19:.*]], label %[[PRED_LOAD_CONTINUE20:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF19:.*]], label %[[PRED_LOAD_CONTINUE20:.*]] ; IC4VF4: [[PRED_LOAD_IF19]]: -; IC4VF4-NEXT: [[TMP23:%.*]] = add i16 [[OFFSET_IDX]], -3 -; IC4VF4-NEXT: [[TMP24:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP23]] +; IC4VF4-NEXT: [[TMP24:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 9 ; IC4VF4-NEXT: [[TMP25:%.*]] = load i16, ptr [[TMP24]], align 1 ; IC4VF4-NEXT: [[TMP26:%.*]] = insertelement <4 x i16> [[TMP21]], i16 [[TMP25]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE20]] ; IC4VF4: [[PRED_LOAD_CONTINUE20]]: ; IC4VF4-NEXT: [[TMP27:%.*]] = phi <4 x i16> [ [[TMP21]], %[[PRED_LOAD_CONTINUE18]] ], [ [[TMP26]], %[[PRED_LOAD_IF19]] ] -; IC4VF4-NEXT: [[TMP28:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP28]], label %[[PRED_LOAD_IF21:.*]], label %[[PRED_LOAD_CONTINUE22:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF21:.*]], label %[[PRED_LOAD_CONTINUE22:.*]] ; IC4VF4: [[PRED_LOAD_IF21]]: -; IC4VF4-NEXT: [[TMP29:%.*]] = add i16 [[OFFSET_IDX]], -4 -; IC4VF4-NEXT: [[TMP30:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP29]] +; IC4VF4-NEXT: [[TMP30:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 8 ; IC4VF4-NEXT: [[TMP31:%.*]] = load i16, ptr [[TMP30]], align 1 ; IC4VF4-NEXT: [[TMP32:%.*]] = insertelement <4 x i16> poison, i16 [[TMP31]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE22]] ; IC4VF4: [[PRED_LOAD_CONTINUE22]]: ; IC4VF4-NEXT: [[TMP33:%.*]] = phi <4 x i16> [ poison, %[[PRED_LOAD_CONTINUE20]] ], [ [[TMP32]], %[[PRED_LOAD_IF21]] ] -; IC4VF4-NEXT: [[TMP34:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP34]], label %[[PRED_LOAD_IF23:.*]], label %[[PRED_LOAD_CONTINUE24:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF23:.*]], label %[[PRED_LOAD_CONTINUE24:.*]] ; IC4VF4: [[PRED_LOAD_IF23]]: -; IC4VF4-NEXT: [[TMP35:%.*]] = add i16 [[OFFSET_IDX]], -5 -; IC4VF4-NEXT: [[TMP36:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP35]] +; IC4VF4-NEXT: [[TMP36:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 7 ; IC4VF4-NEXT: [[TMP37:%.*]] = load i16, ptr [[TMP36]], align 1 ; IC4VF4-NEXT: [[TMP38:%.*]] = insertelement <4 x i16> [[TMP33]], i16 [[TMP37]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE24]] ; IC4VF4: [[PRED_LOAD_CONTINUE24]]: ; IC4VF4-NEXT: [[TMP39:%.*]] = phi <4 x i16> [ [[TMP33]], %[[PRED_LOAD_CONTINUE22]] ], [ [[TMP38]], %[[PRED_LOAD_IF23]] ] -; IC4VF4-NEXT: [[TMP40:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP40]], label %[[PRED_LOAD_IF25:.*]], label %[[PRED_LOAD_CONTINUE26:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF25:.*]], label %[[PRED_LOAD_CONTINUE26:.*]] ; IC4VF4: [[PRED_LOAD_IF25]]: -; IC4VF4-NEXT: [[TMP41:%.*]] = add i16 [[OFFSET_IDX]], -6 -; IC4VF4-NEXT: [[TMP42:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP41]] +; IC4VF4-NEXT: [[TMP42:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 6 ; IC4VF4-NEXT: [[TMP43:%.*]] = load i16, ptr [[TMP42]], align 1 ; IC4VF4-NEXT: [[TMP44:%.*]] = insertelement <4 x i16> [[TMP39]], i16 [[TMP43]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE26]] ; IC4VF4: [[PRED_LOAD_CONTINUE26]]: ; IC4VF4-NEXT: [[TMP45:%.*]] = phi <4 x i16> [ [[TMP39]], %[[PRED_LOAD_CONTINUE24]] ], [ [[TMP44]], %[[PRED_LOAD_IF25]] ] -; IC4VF4-NEXT: [[TMP46:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP46]], label %[[PRED_LOAD_IF27:.*]], label %[[PRED_LOAD_CONTINUE28:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF27:.*]], label %[[PRED_LOAD_CONTINUE28:.*]] ; IC4VF4: [[PRED_LOAD_IF27]]: -; IC4VF4-NEXT: [[TMP47:%.*]] = add i16 [[OFFSET_IDX]], -7 -; IC4VF4-NEXT: [[TMP48:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP47]] +; IC4VF4-NEXT: [[TMP48:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 5 ; IC4VF4-NEXT: [[TMP49:%.*]] = load i16, ptr [[TMP48]], align 1 ; IC4VF4-NEXT: [[TMP50:%.*]] = insertelement <4 x i16> [[TMP45]], i16 [[TMP49]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE28]] ; IC4VF4: [[PRED_LOAD_CONTINUE28]]: ; IC4VF4-NEXT: [[TMP51:%.*]] = phi <4 x i16> [ [[TMP45]], %[[PRED_LOAD_CONTINUE26]] ], [ [[TMP50]], %[[PRED_LOAD_IF27]] ] -; IC4VF4-NEXT: [[TMP52:%.*]] = extractelement <4 x i1> [[TMP2]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP52]], label %[[PRED_LOAD_IF29:.*]], label %[[PRED_LOAD_CONTINUE30:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF29:.*]], label %[[PRED_LOAD_CONTINUE30:.*]] ; IC4VF4: [[PRED_LOAD_IF29]]: -; IC4VF4-NEXT: [[TMP53:%.*]] = add i16 [[OFFSET_IDX]], -8 -; IC4VF4-NEXT: [[TMP54:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP53]] +; IC4VF4-NEXT: [[TMP54:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 4 ; IC4VF4-NEXT: [[TMP55:%.*]] = load i16, ptr [[TMP54]], align 1 ; IC4VF4-NEXT: [[TMP56:%.*]] = insertelement <4 x i16> poison, i16 [[TMP55]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE30]] ; IC4VF4: [[PRED_LOAD_CONTINUE30]]: ; IC4VF4-NEXT: [[TMP57:%.*]] = phi <4 x i16> [ poison, %[[PRED_LOAD_CONTINUE28]] ], [ [[TMP56]], %[[PRED_LOAD_IF29]] ] -; IC4VF4-NEXT: [[TMP58:%.*]] = extractelement <4 x i1> [[TMP2]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP58]], label %[[PRED_LOAD_IF31:.*]], label %[[PRED_LOAD_CONTINUE32:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF31:.*]], label %[[PRED_LOAD_CONTINUE32:.*]] ; IC4VF4: [[PRED_LOAD_IF31]]: -; IC4VF4-NEXT: [[TMP59:%.*]] = add i16 [[OFFSET_IDX]], -9 -; IC4VF4-NEXT: [[TMP60:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP59]] +; IC4VF4-NEXT: [[TMP60:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 3 ; IC4VF4-NEXT: [[TMP61:%.*]] = load i16, ptr [[TMP60]], align 1 ; IC4VF4-NEXT: [[TMP62:%.*]] = insertelement <4 x i16> [[TMP57]], i16 [[TMP61]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE32]] ; IC4VF4: [[PRED_LOAD_CONTINUE32]]: ; IC4VF4-NEXT: [[TMP63:%.*]] = phi <4 x i16> [ [[TMP57]], %[[PRED_LOAD_CONTINUE30]] ], [ [[TMP62]], %[[PRED_LOAD_IF31]] ] -; IC4VF4-NEXT: [[TMP64:%.*]] = extractelement <4 x i1> [[TMP2]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP64]], label %[[PRED_LOAD_IF33:.*]], label %[[PRED_LOAD_CONTINUE34:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF33:.*]], label %[[PRED_LOAD_CONTINUE34:.*]] ; IC4VF4: [[PRED_LOAD_IF33]]: -; IC4VF4-NEXT: [[TMP65:%.*]] = add i16 [[OFFSET_IDX]], -10 -; IC4VF4-NEXT: [[TMP66:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP65]] +; IC4VF4-NEXT: [[TMP66:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 2 ; IC4VF4-NEXT: [[TMP67:%.*]] = load i16, ptr [[TMP66]], align 1 ; IC4VF4-NEXT: [[TMP68:%.*]] = insertelement <4 x i16> [[TMP63]], i16 [[TMP67]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE34]] ; IC4VF4: [[PRED_LOAD_CONTINUE34]]: ; IC4VF4-NEXT: [[TMP69:%.*]] = phi <4 x i16> [ [[TMP63]], %[[PRED_LOAD_CONTINUE32]] ], [ [[TMP68]], %[[PRED_LOAD_IF33]] ] -; IC4VF4-NEXT: [[TMP70:%.*]] = extractelement <4 x i1> [[TMP2]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP70]], label %[[PRED_LOAD_IF35:.*]], label %[[PRED_LOAD_CONTINUE36:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF35:.*]], label %[[PRED_LOAD_CONTINUE36:.*]] ; IC4VF4: [[PRED_LOAD_IF35]]: -; IC4VF4-NEXT: [[TMP71:%.*]] = add i16 [[OFFSET_IDX]], -11 -; IC4VF4-NEXT: [[TMP72:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP71]] +; IC4VF4-NEXT: [[TMP72:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 1 ; IC4VF4-NEXT: [[TMP73:%.*]] = load i16, ptr [[TMP72]], align 1 ; IC4VF4-NEXT: [[TMP74:%.*]] = insertelement <4 x i16> [[TMP69]], i16 [[TMP73]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE36]] ; IC4VF4: [[PRED_LOAD_CONTINUE36]]: ; IC4VF4-NEXT: [[TMP75:%.*]] = phi <4 x i16> [ [[TMP69]], %[[PRED_LOAD_CONTINUE34]] ], [ [[TMP74]], %[[PRED_LOAD_IF35]] ] -; IC4VF4-NEXT: [[TMP76:%.*]] = extractelement <4 x i1> [[TMP3]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP76]], label %[[PRED_LOAD_IF37:.*]], label %[[PRED_LOAD_CONTINUE38:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF37:.*]], label %[[PRED_LOAD_CONTINUE38:.*]] ; IC4VF4: [[PRED_LOAD_IF37]]: -; IC4VF4-NEXT: [[TMP77:%.*]] = add i16 [[OFFSET_IDX]], -12 -; IC4VF4-NEXT: [[TMP78:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP77]] +; IC4VF4-NEXT: [[TMP78:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 0 ; IC4VF4-NEXT: [[TMP79:%.*]] = load i16, ptr [[TMP78]], align 1 ; IC4VF4-NEXT: [[TMP80:%.*]] = insertelement <4 x i16> poison, i16 [[TMP79]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE38]] ; IC4VF4: [[PRED_LOAD_CONTINUE38]]: ; IC4VF4-NEXT: [[TMP81:%.*]] = phi <4 x i16> [ poison, %[[PRED_LOAD_CONTINUE36]] ], [ [[TMP80]], %[[PRED_LOAD_IF37]] ] -; IC4VF4-NEXT: [[TMP82:%.*]] = extractelement <4 x i1> [[TMP3]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP82]], label %[[PRED_LOAD_IF39:.*]], label %[[PRED_LOAD_CONTINUE40:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF39:.*]], label %[[PRED_LOAD_CONTINUE40:.*]] ; IC4VF4: [[PRED_LOAD_IF39]]: -; IC4VF4-NEXT: [[TMP83:%.*]] = add i16 [[OFFSET_IDX]], -13 -; IC4VF4-NEXT: [[TMP84:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP83]] +; IC4VF4-NEXT: [[TMP84:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -1 ; IC4VF4-NEXT: [[TMP85:%.*]] = load i16, ptr [[TMP84]], align 1 ; IC4VF4-NEXT: [[TMP86:%.*]] = insertelement <4 x i16> [[TMP81]], i16 [[TMP85]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE40]] ; IC4VF4: [[PRED_LOAD_CONTINUE40]]: ; IC4VF4-NEXT: [[TMP87:%.*]] = phi <4 x i16> [ [[TMP81]], %[[PRED_LOAD_CONTINUE38]] ], [ [[TMP86]], %[[PRED_LOAD_IF39]] ] -; IC4VF4-NEXT: [[TMP88:%.*]] = extractelement <4 x i1> [[TMP3]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP88]], label %[[PRED_LOAD_IF41:.*]], label %[[PRED_LOAD_CONTINUE42:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF41:.*]], label %[[PRED_LOAD_CONTINUE42:.*]] ; IC4VF4: [[PRED_LOAD_IF41]]: -; IC4VF4-NEXT: [[TMP89:%.*]] = add i16 [[OFFSET_IDX]], -14 -; IC4VF4-NEXT: [[TMP90:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP89]] +; IC4VF4-NEXT: [[TMP90:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -2 ; IC4VF4-NEXT: [[TMP91:%.*]] = load i16, ptr [[TMP90]], align 1 ; IC4VF4-NEXT: [[TMP92:%.*]] = insertelement <4 x i16> [[TMP87]], i16 [[TMP91]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE42]] ; IC4VF4: [[PRED_LOAD_CONTINUE42]]: ; IC4VF4-NEXT: [[TMP93:%.*]] = phi <4 x i16> [ [[TMP87]], %[[PRED_LOAD_CONTINUE40]] ], [ [[TMP92]], %[[PRED_LOAD_IF41]] ] -; IC4VF4-NEXT: [[TMP94:%.*]] = extractelement <4 x i1> [[TMP3]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP94]], label %[[PRED_LOAD_IF43:.*]], label %[[PRED_LOAD_CONTINUE44]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF43:.*]], label %[[PRED_LOAD_CONTINUE44:.*]] ; IC4VF4: [[PRED_LOAD_IF43]]: -; IC4VF4-NEXT: [[TMP95:%.*]] = add i16 [[OFFSET_IDX]], -15 -; IC4VF4-NEXT: [[TMP96:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP95]] +; IC4VF4-NEXT: [[TMP96:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -3 ; IC4VF4-NEXT: [[TMP97:%.*]] = load i16, ptr [[TMP96]], align 1 ; IC4VF4-NEXT: [[TMP98:%.*]] = insertelement <4 x i16> [[TMP93]], i16 [[TMP97]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE44]] @@ -379,22 +326,16 @@ define i16 @select_decreasing_induction_icmp_table_i16(i16 noundef %val) { ; IC4VF4-NEXT: [[TMP101:%.*]] = icmp ugt <4 x i16> [[TMP51]], [[BROADCAST_SPLAT]] ; IC4VF4-NEXT: [[TMP102:%.*]] = icmp ugt <4 x i16> [[TMP75]], [[BROADCAST_SPLAT]] ; IC4VF4-NEXT: [[TMP103:%.*]] = icmp ugt <4 x i16> [[TMP99]], [[BROADCAST_SPLAT]] -; IC4VF4-NEXT: [[TMP104:%.*]] = add nsw <4 x i16> [[VEC_IND]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP105:%.*]] = add nsw <4 x i16> [[STEP_ADD]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP106:%.*]] = add nsw <4 x i16> [[STEP_ADD_2]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP107:%.*]] = add nsw <4 x i16> [[STEP_ADD_3]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP108]] = select <4 x i1> [[TMP100]], <4 x i16> [[TMP104]], <4 x i16> [[VEC_PHI]] -; IC4VF4-NEXT: [[TMP109]] = select <4 x i1> [[TMP101]], <4 x i16> [[TMP105]], <4 x i16> [[VEC_PHI1]] -; IC4VF4-NEXT: [[TMP110]] = select <4 x i1> [[TMP102]], <4 x i16> [[TMP106]], <4 x i16> [[VEC_PHI2]] -; IC4VF4-NEXT: [[TMP111]] = select <4 x i1> [[TMP103]], <4 x i16> [[TMP107]], <4 x i16> [[VEC_PHI3]] -; IC4VF4-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 16 -; IC4VF4-NEXT: [[VEC_IND_NEXT]] = add nsw <4 x i16> [[STEP_ADD_3]], splat (i16 -4) -; IC4VF4-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; IC4VF4-NEXT: [[TMP76:%.*]] = select <4 x i1> [[TMP100]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP77:%.*]] = select <4 x i1> [[TMP101]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP70:%.*]] = select <4 x i1> [[TMP102]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP71:%.*]] = select <4 x i1> [[TMP103]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; IC4VF4: [[MIDDLE_BLOCK]]: -; IC4VF4-NEXT: [[TMP112:%.*]] = select <4 x i1> [[TMP0]], <4 x i16> [[TMP108]], <4 x i16> [[VEC_PHI]] -; IC4VF4-NEXT: [[TMP113:%.*]] = select <4 x i1> [[TMP1]], <4 x i16> [[TMP109]], <4 x i16> [[VEC_PHI1]] -; IC4VF4-NEXT: [[TMP114:%.*]] = select <4 x i1> [[TMP2]], <4 x i16> [[TMP110]], <4 x i16> [[VEC_PHI2]] -; IC4VF4-NEXT: [[TMP115:%.*]] = select <4 x i1> [[TMP3]], <4 x i16> [[TMP111]], <4 x i16> [[VEC_PHI3]] +; IC4VF4-NEXT: [[TMP112:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP76]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP113:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP77]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP114:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP70]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP115:%.*]] = select <4 x i1> zeroinitializer, <4 x i16> [[TMP71]], <4 x i16> splat (i16 32767) ; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP112]], <4 x i16> [[TMP113]]) ; IC4VF4-NEXT: [[RDX_MINMAX45:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP114]]) ; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX45]], <4 x i16> [[TMP115]]) @@ -519,182 +460,129 @@ define i16 @select_decreasing_induction_icmp_table_half(half noundef %val) { ; IC4VF4-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x half> [[BROADCAST_SPLATINSERT]], <4 x half> poison, <4 x i32> zeroinitializer ; IC4VF4-NEXT: br label %[[VECTOR_BODY:.*]] ; IC4VF4: [[VECTOR_BODY]]: -; IC4VF4-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE44:.*]] ] -; IC4VF4-NEXT: [[VEC_IND:%.*]] = phi <4 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP108:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI1:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP109:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP110:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[VEC_PHI3:%.*]] = phi <4 x i16> [ splat (i16 32767), %[[VECTOR_PH]] ], [ [[TMP111:%.*]], %[[PRED_LOAD_CONTINUE44]] ] -; IC4VF4-NEXT: [[STEP_ADD:%.*]] = add <4 x i16> [[VEC_IND]], splat (i16 -4) -; IC4VF4-NEXT: [[STEP_ADD_2:%.*]] = add <4 x i16> [[STEP_ADD]], splat (i16 -4) -; IC4VF4-NEXT: [[STEP_ADD_3:%.*]] = add <4 x i16> [[STEP_ADD_2]], splat (i16 -4) -; IC4VF4-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; IC4VF4-NEXT: [[OFFSET_IDX:%.*]] = sub i16 12, [[DOTCAST]] -; IC4VF4-NEXT: [[BROADCAST_SPLATINSERT4:%.*]] = insertelement <4 x i32> poison, i32 [[INDEX]], i64 0 -; IC4VF4-NEXT: [[BROADCAST_SPLAT5:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT4]], <4 x i32> poison, <4 x i32> zeroinitializer -; IC4VF4-NEXT: [[VEC_IV:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV8:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV11:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[VEC_IV14:%.*]] = add <4 x i32> [[BROADCAST_SPLAT5]], -; IC4VF4-NEXT: [[TMP0:%.*]] = icmp ule <4 x i32> [[VEC_IV]], splat (i32 11) -; IC4VF4-NEXT: [[TMP1:%.*]] = icmp ule <4 x i32> [[VEC_IV8]], splat (i32 11) -; IC4VF4-NEXT: [[TMP2:%.*]] = icmp ule <4 x i32> [[VEC_IV11]], splat (i32 11) -; IC4VF4-NEXT: [[TMP3:%.*]] = icmp ule <4 x i32> [[VEC_IV14]], splat (i32 11) -; IC4VF4-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP0]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP4]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] ; IC4VF4: [[PRED_LOAD_IF]]: -; IC4VF4-NEXT: [[TMP5:%.*]] = add i16 [[OFFSET_IDX]], 0 -; IC4VF4-NEXT: [[TMP6:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP5]] +; IC4VF4-NEXT: [[TMP6:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 12 ; IC4VF4-NEXT: [[TMP7:%.*]] = load half, ptr [[TMP6]], align 1 ; IC4VF4-NEXT: [[TMP8:%.*]] = insertelement <4 x half> poison, half [[TMP7]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE]] ; IC4VF4: [[PRED_LOAD_CONTINUE]]: ; IC4VF4-NEXT: [[TMP9:%.*]] = phi <4 x half> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ] -; IC4VF4-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP0]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP10]], label %[[PRED_LOAD_IF15:.*]], label %[[PRED_LOAD_CONTINUE16:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF15:.*]], label %[[PRED_LOAD_CONTINUE16:.*]] ; IC4VF4: [[PRED_LOAD_IF15]]: -; IC4VF4-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], -1 -; IC4VF4-NEXT: [[TMP12:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP11]] +; IC4VF4-NEXT: [[TMP12:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 11 ; IC4VF4-NEXT: [[TMP13:%.*]] = load half, ptr [[TMP12]], align 1 ; IC4VF4-NEXT: [[TMP14:%.*]] = insertelement <4 x half> [[TMP9]], half [[TMP13]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE16]] ; IC4VF4: [[PRED_LOAD_CONTINUE16]]: ; IC4VF4-NEXT: [[TMP15:%.*]] = phi <4 x half> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF15]] ] -; IC4VF4-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP0]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP16]], label %[[PRED_LOAD_IF17:.*]], label %[[PRED_LOAD_CONTINUE18:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF17:.*]], label %[[PRED_LOAD_CONTINUE18:.*]] ; IC4VF4: [[PRED_LOAD_IF17]]: -; IC4VF4-NEXT: [[TMP17:%.*]] = add i16 [[OFFSET_IDX]], -2 -; IC4VF4-NEXT: [[TMP18:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP17]] +; IC4VF4-NEXT: [[TMP18:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 10 ; IC4VF4-NEXT: [[TMP19:%.*]] = load half, ptr [[TMP18]], align 1 ; IC4VF4-NEXT: [[TMP20:%.*]] = insertelement <4 x half> [[TMP15]], half [[TMP19]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE18]] ; IC4VF4: [[PRED_LOAD_CONTINUE18]]: ; IC4VF4-NEXT: [[TMP21:%.*]] = phi <4 x half> [ [[TMP15]], %[[PRED_LOAD_CONTINUE16]] ], [ [[TMP20]], %[[PRED_LOAD_IF17]] ] -; IC4VF4-NEXT: [[TMP22:%.*]] = extractelement <4 x i1> [[TMP0]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP22]], label %[[PRED_LOAD_IF19:.*]], label %[[PRED_LOAD_CONTINUE20:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF19:.*]], label %[[PRED_LOAD_CONTINUE20:.*]] ; IC4VF4: [[PRED_LOAD_IF19]]: -; IC4VF4-NEXT: [[TMP23:%.*]] = add i16 [[OFFSET_IDX]], -3 -; IC4VF4-NEXT: [[TMP24:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP23]] +; IC4VF4-NEXT: [[TMP24:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 9 ; IC4VF4-NEXT: [[TMP25:%.*]] = load half, ptr [[TMP24]], align 1 ; IC4VF4-NEXT: [[TMP26:%.*]] = insertelement <4 x half> [[TMP21]], half [[TMP25]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE20]] ; IC4VF4: [[PRED_LOAD_CONTINUE20]]: ; IC4VF4-NEXT: [[TMP27:%.*]] = phi <4 x half> [ [[TMP21]], %[[PRED_LOAD_CONTINUE18]] ], [ [[TMP26]], %[[PRED_LOAD_IF19]] ] -; IC4VF4-NEXT: [[TMP28:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP28]], label %[[PRED_LOAD_IF21:.*]], label %[[PRED_LOAD_CONTINUE22:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF21:.*]], label %[[PRED_LOAD_CONTINUE22:.*]] ; IC4VF4: [[PRED_LOAD_IF21]]: -; IC4VF4-NEXT: [[TMP29:%.*]] = add i16 [[OFFSET_IDX]], -4 -; IC4VF4-NEXT: [[TMP30:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP29]] +; IC4VF4-NEXT: [[TMP30:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 8 ; IC4VF4-NEXT: [[TMP31:%.*]] = load half, ptr [[TMP30]], align 1 ; IC4VF4-NEXT: [[TMP32:%.*]] = insertelement <4 x half> poison, half [[TMP31]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE22]] ; IC4VF4: [[PRED_LOAD_CONTINUE22]]: ; IC4VF4-NEXT: [[TMP33:%.*]] = phi <4 x half> [ poison, %[[PRED_LOAD_CONTINUE20]] ], [ [[TMP32]], %[[PRED_LOAD_IF21]] ] -; IC4VF4-NEXT: [[TMP34:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP34]], label %[[PRED_LOAD_IF23:.*]], label %[[PRED_LOAD_CONTINUE24:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF23:.*]], label %[[PRED_LOAD_CONTINUE24:.*]] ; IC4VF4: [[PRED_LOAD_IF23]]: -; IC4VF4-NEXT: [[TMP35:%.*]] = add i16 [[OFFSET_IDX]], -5 -; IC4VF4-NEXT: [[TMP36:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP35]] +; IC4VF4-NEXT: [[TMP36:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 7 ; IC4VF4-NEXT: [[TMP37:%.*]] = load half, ptr [[TMP36]], align 1 ; IC4VF4-NEXT: [[TMP38:%.*]] = insertelement <4 x half> [[TMP33]], half [[TMP37]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE24]] ; IC4VF4: [[PRED_LOAD_CONTINUE24]]: ; IC4VF4-NEXT: [[TMP39:%.*]] = phi <4 x half> [ [[TMP33]], %[[PRED_LOAD_CONTINUE22]] ], [ [[TMP38]], %[[PRED_LOAD_IF23]] ] -; IC4VF4-NEXT: [[TMP40:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP40]], label %[[PRED_LOAD_IF25:.*]], label %[[PRED_LOAD_CONTINUE26:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF25:.*]], label %[[PRED_LOAD_CONTINUE26:.*]] ; IC4VF4: [[PRED_LOAD_IF25]]: -; IC4VF4-NEXT: [[TMP41:%.*]] = add i16 [[OFFSET_IDX]], -6 -; IC4VF4-NEXT: [[TMP42:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP41]] +; IC4VF4-NEXT: [[TMP42:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 6 ; IC4VF4-NEXT: [[TMP43:%.*]] = load half, ptr [[TMP42]], align 1 ; IC4VF4-NEXT: [[TMP44:%.*]] = insertelement <4 x half> [[TMP39]], half [[TMP43]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE26]] ; IC4VF4: [[PRED_LOAD_CONTINUE26]]: ; IC4VF4-NEXT: [[TMP45:%.*]] = phi <4 x half> [ [[TMP39]], %[[PRED_LOAD_CONTINUE24]] ], [ [[TMP44]], %[[PRED_LOAD_IF25]] ] -; IC4VF4-NEXT: [[TMP46:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP46]], label %[[PRED_LOAD_IF27:.*]], label %[[PRED_LOAD_CONTINUE28:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF27:.*]], label %[[PRED_LOAD_CONTINUE28:.*]] ; IC4VF4: [[PRED_LOAD_IF27]]: -; IC4VF4-NEXT: [[TMP47:%.*]] = add i16 [[OFFSET_IDX]], -7 -; IC4VF4-NEXT: [[TMP48:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP47]] +; IC4VF4-NEXT: [[TMP48:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 5 ; IC4VF4-NEXT: [[TMP49:%.*]] = load half, ptr [[TMP48]], align 1 ; IC4VF4-NEXT: [[TMP50:%.*]] = insertelement <4 x half> [[TMP45]], half [[TMP49]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE28]] ; IC4VF4: [[PRED_LOAD_CONTINUE28]]: ; IC4VF4-NEXT: [[TMP51:%.*]] = phi <4 x half> [ [[TMP45]], %[[PRED_LOAD_CONTINUE26]] ], [ [[TMP50]], %[[PRED_LOAD_IF27]] ] -; IC4VF4-NEXT: [[TMP52:%.*]] = extractelement <4 x i1> [[TMP2]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP52]], label %[[PRED_LOAD_IF29:.*]], label %[[PRED_LOAD_CONTINUE30:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF29:.*]], label %[[PRED_LOAD_CONTINUE30:.*]] ; IC4VF4: [[PRED_LOAD_IF29]]: -; IC4VF4-NEXT: [[TMP53:%.*]] = add i16 [[OFFSET_IDX]], -8 -; IC4VF4-NEXT: [[TMP54:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP53]] +; IC4VF4-NEXT: [[TMP54:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 4 ; IC4VF4-NEXT: [[TMP55:%.*]] = load half, ptr [[TMP54]], align 1 ; IC4VF4-NEXT: [[TMP56:%.*]] = insertelement <4 x half> poison, half [[TMP55]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE30]] ; IC4VF4: [[PRED_LOAD_CONTINUE30]]: ; IC4VF4-NEXT: [[TMP57:%.*]] = phi <4 x half> [ poison, %[[PRED_LOAD_CONTINUE28]] ], [ [[TMP56]], %[[PRED_LOAD_IF29]] ] -; IC4VF4-NEXT: [[TMP58:%.*]] = extractelement <4 x i1> [[TMP2]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP58]], label %[[PRED_LOAD_IF31:.*]], label %[[PRED_LOAD_CONTINUE32:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF31:.*]], label %[[PRED_LOAD_CONTINUE32:.*]] ; IC4VF4: [[PRED_LOAD_IF31]]: -; IC4VF4-NEXT: [[TMP59:%.*]] = add i16 [[OFFSET_IDX]], -9 -; IC4VF4-NEXT: [[TMP60:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP59]] +; IC4VF4-NEXT: [[TMP60:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 3 ; IC4VF4-NEXT: [[TMP61:%.*]] = load half, ptr [[TMP60]], align 1 ; IC4VF4-NEXT: [[TMP62:%.*]] = insertelement <4 x half> [[TMP57]], half [[TMP61]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE32]] ; IC4VF4: [[PRED_LOAD_CONTINUE32]]: ; IC4VF4-NEXT: [[TMP63:%.*]] = phi <4 x half> [ [[TMP57]], %[[PRED_LOAD_CONTINUE30]] ], [ [[TMP62]], %[[PRED_LOAD_IF31]] ] -; IC4VF4-NEXT: [[TMP64:%.*]] = extractelement <4 x i1> [[TMP2]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP64]], label %[[PRED_LOAD_IF33:.*]], label %[[PRED_LOAD_CONTINUE34:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF33:.*]], label %[[PRED_LOAD_CONTINUE34:.*]] ; IC4VF4: [[PRED_LOAD_IF33]]: -; IC4VF4-NEXT: [[TMP65:%.*]] = add i16 [[OFFSET_IDX]], -10 -; IC4VF4-NEXT: [[TMP66:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP65]] +; IC4VF4-NEXT: [[TMP66:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 2 ; IC4VF4-NEXT: [[TMP67:%.*]] = load half, ptr [[TMP66]], align 1 ; IC4VF4-NEXT: [[TMP68:%.*]] = insertelement <4 x half> [[TMP63]], half [[TMP67]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE34]] ; IC4VF4: [[PRED_LOAD_CONTINUE34]]: ; IC4VF4-NEXT: [[TMP69:%.*]] = phi <4 x half> [ [[TMP63]], %[[PRED_LOAD_CONTINUE32]] ], [ [[TMP68]], %[[PRED_LOAD_IF33]] ] -; IC4VF4-NEXT: [[TMP70:%.*]] = extractelement <4 x i1> [[TMP2]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP70]], label %[[PRED_LOAD_IF35:.*]], label %[[PRED_LOAD_CONTINUE36:.*]] +; IC4VF4-NEXT: br i1 true, label %[[PRED_LOAD_IF35:.*]], label %[[PRED_LOAD_CONTINUE36:.*]] ; IC4VF4: [[PRED_LOAD_IF35]]: -; IC4VF4-NEXT: [[TMP71:%.*]] = add i16 [[OFFSET_IDX]], -11 -; IC4VF4-NEXT: [[TMP72:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP71]] +; IC4VF4-NEXT: [[TMP72:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 1 ; IC4VF4-NEXT: [[TMP73:%.*]] = load half, ptr [[TMP72]], align 1 ; IC4VF4-NEXT: [[TMP74:%.*]] = insertelement <4 x half> [[TMP69]], half [[TMP73]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE36]] ; IC4VF4: [[PRED_LOAD_CONTINUE36]]: ; IC4VF4-NEXT: [[TMP75:%.*]] = phi <4 x half> [ [[TMP69]], %[[PRED_LOAD_CONTINUE34]] ], [ [[TMP74]], %[[PRED_LOAD_IF35]] ] -; IC4VF4-NEXT: [[TMP76:%.*]] = extractelement <4 x i1> [[TMP3]], i32 0 -; IC4VF4-NEXT: br i1 [[TMP76]], label %[[PRED_LOAD_IF37:.*]], label %[[PRED_LOAD_CONTINUE38:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF37:.*]], label %[[PRED_LOAD_CONTINUE38:.*]] ; IC4VF4: [[PRED_LOAD_IF37]]: -; IC4VF4-NEXT: [[TMP77:%.*]] = add i16 [[OFFSET_IDX]], -12 -; IC4VF4-NEXT: [[TMP78:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP77]] +; IC4VF4-NEXT: [[TMP78:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 0 ; IC4VF4-NEXT: [[TMP79:%.*]] = load half, ptr [[TMP78]], align 1 ; IC4VF4-NEXT: [[TMP80:%.*]] = insertelement <4 x half> poison, half [[TMP79]], i32 0 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE38]] ; IC4VF4: [[PRED_LOAD_CONTINUE38]]: ; IC4VF4-NEXT: [[TMP81:%.*]] = phi <4 x half> [ poison, %[[PRED_LOAD_CONTINUE36]] ], [ [[TMP80]], %[[PRED_LOAD_IF37]] ] -; IC4VF4-NEXT: [[TMP82:%.*]] = extractelement <4 x i1> [[TMP3]], i32 1 -; IC4VF4-NEXT: br i1 [[TMP82]], label %[[PRED_LOAD_IF39:.*]], label %[[PRED_LOAD_CONTINUE40:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF39:.*]], label %[[PRED_LOAD_CONTINUE40:.*]] ; IC4VF4: [[PRED_LOAD_IF39]]: -; IC4VF4-NEXT: [[TMP83:%.*]] = add i16 [[OFFSET_IDX]], -13 -; IC4VF4-NEXT: [[TMP84:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP83]] +; IC4VF4-NEXT: [[TMP84:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -1 ; IC4VF4-NEXT: [[TMP85:%.*]] = load half, ptr [[TMP84]], align 1 ; IC4VF4-NEXT: [[TMP86:%.*]] = insertelement <4 x half> [[TMP81]], half [[TMP85]], i32 1 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE40]] ; IC4VF4: [[PRED_LOAD_CONTINUE40]]: ; IC4VF4-NEXT: [[TMP87:%.*]] = phi <4 x half> [ [[TMP81]], %[[PRED_LOAD_CONTINUE38]] ], [ [[TMP86]], %[[PRED_LOAD_IF39]] ] -; IC4VF4-NEXT: [[TMP88:%.*]] = extractelement <4 x i1> [[TMP3]], i32 2 -; IC4VF4-NEXT: br i1 [[TMP88]], label %[[PRED_LOAD_IF41:.*]], label %[[PRED_LOAD_CONTINUE42:.*]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF41:.*]], label %[[PRED_LOAD_CONTINUE42:.*]] ; IC4VF4: [[PRED_LOAD_IF41]]: -; IC4VF4-NEXT: [[TMP89:%.*]] = add i16 [[OFFSET_IDX]], -14 -; IC4VF4-NEXT: [[TMP90:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP89]] +; IC4VF4-NEXT: [[TMP90:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -2 ; IC4VF4-NEXT: [[TMP91:%.*]] = load half, ptr [[TMP90]], align 1 ; IC4VF4-NEXT: [[TMP92:%.*]] = insertelement <4 x half> [[TMP87]], half [[TMP91]], i32 2 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE42]] ; IC4VF4: [[PRED_LOAD_CONTINUE42]]: ; IC4VF4-NEXT: [[TMP93:%.*]] = phi <4 x half> [ [[TMP87]], %[[PRED_LOAD_CONTINUE40]] ], [ [[TMP92]], %[[PRED_LOAD_IF41]] ] -; IC4VF4-NEXT: [[TMP94:%.*]] = extractelement <4 x i1> [[TMP3]], i32 3 -; IC4VF4-NEXT: br i1 [[TMP94]], label %[[PRED_LOAD_IF43:.*]], label %[[PRED_LOAD_CONTINUE44]] +; IC4VF4-NEXT: br i1 false, label %[[PRED_LOAD_IF43:.*]], label %[[PRED_LOAD_CONTINUE44:.*]] ; IC4VF4: [[PRED_LOAD_IF43]]: -; IC4VF4-NEXT: [[TMP95:%.*]] = add i16 [[OFFSET_IDX]], -15 -; IC4VF4-NEXT: [[TMP96:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 [[TMP95]] +; IC4VF4-NEXT: [[TMP96:%.*]] = getelementptr inbounds [13 x i16], ptr @table, i16 0, i16 -3 ; IC4VF4-NEXT: [[TMP97:%.*]] = load half, ptr [[TMP96]], align 1 ; IC4VF4-NEXT: [[TMP98:%.*]] = insertelement <4 x half> [[TMP93]], half [[TMP97]], i32 3 ; IC4VF4-NEXT: br label %[[PRED_LOAD_CONTINUE44]] @@ -704,22 +592,16 @@ define i16 @select_decreasing_induction_icmp_table_half(half noundef %val) { ; IC4VF4-NEXT: [[TMP101:%.*]] = fcmp ugt <4 x half> [[TMP51]], [[BROADCAST_SPLAT]] ; IC4VF4-NEXT: [[TMP102:%.*]] = fcmp ugt <4 x half> [[TMP75]], [[BROADCAST_SPLAT]] ; IC4VF4-NEXT: [[TMP103:%.*]] = fcmp ugt <4 x half> [[TMP99]], [[BROADCAST_SPLAT]] -; IC4VF4-NEXT: [[TMP104:%.*]] = add nsw <4 x i16> [[VEC_IND]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP105:%.*]] = add nsw <4 x i16> [[STEP_ADD]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP106:%.*]] = add nsw <4 x i16> [[STEP_ADD_2]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP107:%.*]] = add nsw <4 x i16> [[STEP_ADD_3]], splat (i16 -1) -; IC4VF4-NEXT: [[TMP108]] = select <4 x i1> [[TMP100]], <4 x i16> [[TMP104]], <4 x i16> [[VEC_PHI]] -; IC4VF4-NEXT: [[TMP109]] = select <4 x i1> [[TMP101]], <4 x i16> [[TMP105]], <4 x i16> [[VEC_PHI1]] -; IC4VF4-NEXT: [[TMP110]] = select <4 x i1> [[TMP102]], <4 x i16> [[TMP106]], <4 x i16> [[VEC_PHI2]] -; IC4VF4-NEXT: [[TMP111]] = select <4 x i1> [[TMP103]], <4 x i16> [[TMP107]], <4 x i16> [[VEC_PHI3]] -; IC4VF4-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 16 -; IC4VF4-NEXT: [[VEC_IND_NEXT]] = add nsw <4 x i16> [[STEP_ADD_3]], splat (i16 -4) -; IC4VF4-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; IC4VF4-NEXT: [[TMP76:%.*]] = select <4 x i1> [[TMP100]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP77:%.*]] = select <4 x i1> [[TMP101]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP70:%.*]] = select <4 x i1> [[TMP102]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP71:%.*]] = select <4 x i1> [[TMP103]], <4 x i16> , <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; IC4VF4: [[MIDDLE_BLOCK]]: -; IC4VF4-NEXT: [[TMP112:%.*]] = select <4 x i1> [[TMP0]], <4 x i16> [[TMP108]], <4 x i16> [[VEC_PHI]] -; IC4VF4-NEXT: [[TMP113:%.*]] = select <4 x i1> [[TMP1]], <4 x i16> [[TMP109]], <4 x i16> [[VEC_PHI1]] -; IC4VF4-NEXT: [[TMP114:%.*]] = select <4 x i1> [[TMP2]], <4 x i16> [[TMP110]], <4 x i16> [[VEC_PHI2]] -; IC4VF4-NEXT: [[TMP115:%.*]] = select <4 x i1> [[TMP3]], <4 x i16> [[TMP111]], <4 x i16> [[VEC_PHI3]] +; IC4VF4-NEXT: [[TMP112:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP76]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP113:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP77]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP114:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP70]], <4 x i16> splat (i16 32767) +; IC4VF4-NEXT: [[TMP115:%.*]] = select <4 x i1> zeroinitializer, <4 x i16> [[TMP71]], <4 x i16> splat (i16 32767) ; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP112]], <4 x i16> [[TMP113]]) ; IC4VF4-NEXT: [[RDX_MINMAX45:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP114]]) ; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX45]], <4 x i16> [[TMP115]]) @@ -873,7 +755,7 @@ define i64 @select_decreasing_induction_icmp_iv_unsigned(ptr %a) { ; IC4VF4-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; IC4VF4-NEXT: [[VEC_IND_NEXT]] = add nsw <4 x i64> [[STEP_ADD_3]], splat (i64 -4) ; IC4VF4-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], -9223372036854775808 -; IC4VF4-NEXT: br i1 [[TMP17]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; IC4VF4-NEXT: br i1 [[TMP17]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] ; IC4VF4: [[MIDDLE_BLOCK]]: ; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i64> @llvm.umin.v4i64(<4 x i64> [[TMP13]], <4 x i64> [[TMP14]]) ; IC4VF4-NEXT: [[RDX_MINMAX10:%.*]] = call <4 x i64> @llvm.umin.v4i64(<4 x i64> [[RDX_MINMAX]], <4 x i64> [[TMP15]]) @@ -1102,7 +984,7 @@ define i64 @select_decreasing_induction_icmp_iv_just_within_bounds(ptr %a, ptr % ; IC4VF4-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; IC4VF4-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[STEP_ADD_3]], splat (i64 -4) ; IC4VF4-NEXT: [[TMP31:%.*]] = icmp eq i64 [[INDEX_NEXT]], -16 -; IC4VF4-NEXT: br i1 [[TMP31]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; IC4VF4-NEXT: br i1 [[TMP31]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; IC4VF4: [[MIDDLE_BLOCK]]: ; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i64> @llvm.umin.v4i64(<4 x i64> [[TMP27]], <4 x i64> [[TMP28]]) ; IC4VF4-NEXT: [[RDX_MINMAX18:%.*]] = call <4 x i64> @llvm.umin.v4i64(<4 x i64> [[RDX_MINMAX]], <4 x i64> [[TMP29]]) @@ -1124,7 +1006,7 @@ define i64 @select_decreasing_induction_icmp_iv_just_within_bounds(ptr %a, ptr % ; IC4VF4-NEXT: [[CMP_A_B:%.*]] = icmp sgt i8 [[LD_A]], [[LD_B]] ; IC4VF4-NEXT: [[COND]] = select i1 [[CMP_A_B]], i64 [[IV_NEXT]], i64 [[RDX]] ; IC4VF4-NEXT: [[EXIT_COND:%.*]] = icmp eq i64 [[IV_NEXT]], 0 -; IC4VF4-NEXT: br i1 [[EXIT_COND]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] +; IC4VF4-NEXT: br i1 [[EXIT_COND]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] ; IC4VF4: [[EXIT]]: ; IC4VF4-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], %[[LOOP]] ] ; IC4VF4-NEXT: ret i64 [[COND_LCSSA]] @@ -1363,7 +1245,7 @@ define i64 @select_decreasing_induction_icmp_non_const_start(ptr %a, ptr %b, i64 ; IC4VF4-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; IC4VF4-NEXT: [[VEC_IND_NEXT]] = add nsw <4 x i64> [[STEP_ADD_3]], splat (i64 -4) ; IC4VF4-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; IC4VF4-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; IC4VF4-NEXT: br i1 [[TMP16]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; IC4VF4: [[MIDDLE_BLOCK]]: ; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i64> @llvm.smin.v4i64(<4 x i64> [[TMP34]], <4 x i64> [[TMP35]]) ; IC4VF4-NEXT: [[RDX_MINMAX23:%.*]] = call <4 x i64> @llvm.smin.v4i64(<4 x i64> [[RDX_MINMAX]], <4 x i64> [[TMP36]]) @@ -1392,7 +1274,7 @@ define i64 @select_decreasing_induction_icmp_non_const_start(ptr %a, ptr %b, i64 ; IC4VF4-NEXT: [[CMP_A_B:%.*]] = icmp sgt i64 [[LD_A]], [[LD_B]] ; IC4VF4-NEXT: [[COND]] = select i1 [[CMP_A_B]], i64 [[IV_NEXT]], i64 [[RDX]] ; IC4VF4-NEXT: [[EXIT_COND:%.*]] = icmp ugt i64 [[IV]], 1 -; IC4VF4-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP9:![0-9]+]] +; IC4VF4-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP7:![0-9]+]] ; IC4VF4: [[EXIT]]: ; IC4VF4-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], %[[LOOP]] ], [ [[RDX_SELECT]], %[[MIDDLE_BLOCK]] ] ; IC4VF4-NEXT: ret i64 [[COND_LCSSA]] diff --git a/llvm/test/Transforms/LoopVectorize/load-deref-pred-poison-ub-ops-feeding-pointer.ll b/llvm/test/Transforms/LoopVectorize/load-deref-pred-poison-ub-ops-feeding-pointer.ll index 5e88072517b37..b5b1879ec6c25 100644 --- a/llvm/test/Transforms/LoopVectorize/load-deref-pred-poison-ub-ops-feeding-pointer.ll +++ b/llvm/test/Transforms/LoopVectorize/load-deref-pred-poison-ub-ops-feeding-pointer.ll @@ -17,58 +17,45 @@ define void @ptr_depends_on_sdiv(ptr noalias %dst, i16 noundef %off) { ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE4:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE4]] ] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]] -; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10) -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP0]], i32 0 -; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_SDIV_IF:.*]], label %[[PRED_SDIV_CONTINUE:.*]] +; CHECK-NEXT: br i1 false, label %[[PRED_SDIV_IF:.*]], label %[[PRED_SDIV_CONTINUE:.*]] ; CHECK: [[PRED_SDIV_IF]]: ; CHECK-NEXT: [[TMP2:%.*]] = sdiv i16 24316, [[OFF]] ; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i16> poison, i16 [[TMP2]], i32 0 ; CHECK-NEXT: br label %[[PRED_SDIV_CONTINUE]] ; CHECK: [[PRED_SDIV_CONTINUE]]: ; CHECK-NEXT: [[TMP4:%.*]] = phi <2 x i16> [ poison, %[[VECTOR_BODY]] ], [ [[TMP3]], %[[PRED_SDIV_IF]] ] -; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i1> [[TMP0]], i32 1 -; CHECK-NEXT: br i1 [[TMP14]], label %[[PRED_SDIV_IF1:.*]], label %[[PRED_SDIV_CONTINUE2:.*]] +; CHECK-NEXT: br i1 true, label %[[PRED_SDIV_IF1:.*]], label %[[PRED_SDIV_CONTINUE2:.*]] ; CHECK: [[PRED_SDIV_IF1]]: ; CHECK-NEXT: [[TMP18:%.*]] = sdiv i16 24316, [[OFF]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i16> [[TMP4]], i16 [[TMP18]], i32 1 ; CHECK-NEXT: br label %[[PRED_SDIV_CONTINUE2]] ; CHECK: [[PRED_SDIV_CONTINUE2]]: ; CHECK-NEXT: [[TMP8:%.*]] = phi <2 x i16> [ [[TMP4]], %[[PRED_SDIV_CONTINUE]] ], [ [[TMP7]], %[[PRED_SDIV_IF1]] ] -; CHECK-NEXT: [[TMP21:%.*]] = add <2 x i16> [[VEC_IND]], splat (i16 16383) ; CHECK-NEXT: [[TMP22:%.*]] = shl <2 x i16> [[TMP8]], splat (i16 14) -; CHECK-NEXT: [[TMP23:%.*]] = sub <2 x i16> [[TMP21]], [[TMP22]] -; CHECK-NEXT: [[TMP19:%.*]] = extractelement <2 x i1> [[TMP0]], i32 0 -; CHECK-NEXT: br i1 [[TMP19]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; CHECK-NEXT: [[TMP23:%.*]] = sub <2 x i16> , [[TMP22]] +; CHECK-NEXT: br i1 false, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; CHECK: [[PRED_STORE_IF]]: ; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i16> [[TMP23]], i32 0 ; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP13]] ; CHECK-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP24]], align 1 -; CHECK-NEXT: [[TMP10:%.*]] = add i16 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP10]] +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 9 ; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP11]], align 1 ; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]] ; CHECK: [[PRED_STORE_CONTINUE]]: -; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i1> [[TMP0]], i32 1 -; CHECK-NEXT: br i1 [[TMP12]], label %[[PRED_STORE_IF3:.*]], label %[[PRED_STORE_CONTINUE4]] +; CHECK-NEXT: br i1 true, label %[[PRED_STORE_IF3:.*]], label %[[EXIT:.*]] ; CHECK: [[PRED_STORE_IF3]]: ; CHECK-NEXT: [[TMP25:%.*]] = extractelement <2 x i16> [[TMP23]], i32 1 ; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP25]] ; CHECK-NEXT: [[TMP15:%.*]] = load i64, ptr [[TMP20]], align 1 -; CHECK-NEXT: [[TMP16:%.*]] = add i16 [[OFFSET_IDX]], 1 -; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP16]] +; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 10 ; CHECK-NEXT: store i64 [[TMP15]], ptr [[TMP17]], align 1 -; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE4]] -; CHECK: [[PRED_STORE_CONTINUE4]]: -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br [[EXIT:label %.*]] -; CHECK: [[SCALAR_PH:.*:]] +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[SCALAR_PH:.*]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: +; CHECK-NEXT: ret void ; entry: br label %loop.header @@ -111,40 +98,30 @@ define void @ptr_depends_on_possibly_poison_value(ptr noalias %dst, i16 %off) { ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i16> [[TMP0]], [[BROADCAST_SPLAT]] ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10) -; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i16> [[VEC_IND]], [[TMP1]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0 -; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i16> , [[TMP1]] +; CHECK-NEXT: br i1 false, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; CHECK: [[PRED_STORE_IF]]: ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i16> [[TMP3]], i32 0 ; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP5]] ; CHECK-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP14]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = add i16 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP7]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 9 ; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP8]], align 1 ; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]] ; CHECK: [[PRED_STORE_CONTINUE]]: -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1 -; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]] +; CHECK-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[EXIT:.*]] ; CHECK: [[PRED_STORE_IF1]]: ; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x i16> [[TMP3]], i32 1 ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP15]] ; CHECK-NEXT: [[TMP13:%.*]] = load i64, ptr [[TMP16]], align 1 -; CHECK-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], 1 -; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP11]] +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 10 ; CHECK-NEXT: store i64 [[TMP13]], ptr [[TMP12]], align 1 -; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]] -; CHECK: [[PRED_STORE_CONTINUE2]]: -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br [[EXIT:label %.*]] -; CHECK: [[SCALAR_PH:.*:]] +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[SCALAR_PH:.*]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: +; CHECK-NEXT: ret void ; entry: br label %loop.header @@ -183,38 +160,28 @@ define void @ptr_doesnt_depend_on_poison_or_ub(ptr noalias %dst, i16 noundef %of ; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], [[OFF]] ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10) -; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[OFFSET_IDX]], [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = add i16 9, [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i64, ptr @src, i16 [[TMP3]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP4]], align 1 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0 -; CHECK-NEXT: br i1 [[TMP6]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; CHECK-NEXT: br i1 false, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; CHECK: [[PRED_STORE_IF]]: -; CHECK-NEXT: [[TMP7:%.*]] = add i16 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP7]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 9 ; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0 ; CHECK-NEXT: store i64 [[TMP9]], ptr [[TMP8]], align 1 ; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]] ; CHECK: [[PRED_STORE_CONTINUE]]: -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1 -; CHECK-NEXT: br i1 [[TMP10]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]] +; CHECK-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[EXIT:.*]] ; CHECK: [[PRED_STORE_IF1]]: -; CHECK-NEXT: [[TMP11:%.*]] = add i16 [[OFFSET_IDX]], 1 -; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP11]] +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 10 ; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1 ; CHECK-NEXT: store i64 [[TMP13]], ptr [[TMP12]], align 1 -; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]] -; CHECK: [[PRED_STORE_CONTINUE2]]: -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br [[EXIT:label %.*]] -; CHECK: [[SCALAR_PH:.*:]] +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[SCALAR_PH:.*]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: +; CHECK-NEXT: ret void ; entry: br label %loop.header @@ -252,45 +219,35 @@ define void @ptr_depends_on_possibly_poison_value_from_load(ptr noalias %dst) { ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]] ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @src, align 1 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i16> poison, i16 [[TMP0]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i16> [[BROADCAST_SPLATINSERT]], <2 x i16> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10) ; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i16> splat (i16 1), [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i16> [[TMP2]], [[BROADCAST_SPLAT]] -; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i16> [[VEC_IND]], [[TMP3]] -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i1> [[TMP1]], i32 0 -; CHECK-NEXT: br i1 [[TMP7]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i16> , [[TMP3]] +; CHECK-NEXT: br i1 false, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; CHECK: [[PRED_STORE_IF]]: ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i16> [[TMP4]], i32 0 ; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP6]] ; CHECK-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP15]], align 1 -; CHECK-NEXT: [[TMP8:%.*]] = add i16 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP8]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 9 ; CHECK-NEXT: store i64 [[TMP10]], ptr [[TMP9]], align 1 ; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]] ; CHECK: [[PRED_STORE_CONTINUE]]: -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP1]], i32 1 -; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]] +; CHECK-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[EXIT:.*]] ; CHECK: [[PRED_STORE_IF1]]: ; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x i16> [[TMP4]], i32 1 ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i64, ptr @src, i16 [[TMP16]] ; CHECK-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP17]], align 1 -; CHECK-NEXT: [[TMP12:%.*]] = add i16 [[OFFSET_IDX]], 1 -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP12]] +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 10 ; CHECK-NEXT: store i64 [[TMP14]], ptr [[TMP13]], align 1 -; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]] -; CHECK: [[PRED_STORE_CONTINUE2]]: -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br [[EXIT:label %.*]] -; CHECK: [[SCALAR_PH:.*:]] +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[SCALAR_PH:.*]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: +; CHECK-NEXT: ret void ; entry: br label %loop.header @@ -329,41 +286,31 @@ define void @ptr_depends_on_noundef_load(ptr noalias %dst) { ; CHECK: [[VECTOR_PH]]: ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_STORE_CONTINUE2:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i16> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_STORE_CONTINUE2]] ] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i32 [[INDEX]] to i16 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i16 9, [[DOTCAST]] -; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @src, align 1, !noundef [[META10:![0-9]+]] -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[VEC_IND]], splat (i16 10) +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @src, align 1, !noundef [[META0:![0-9]+]] ; CHECK-NEXT: [[TMP2:%.*]] = sub i16 1, [[TMP0]] ; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = add i16 [[OFFSET_IDX]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = add i16 9, [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr @src, i16 [[TMP4]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i1> [[TMP1]], i32 0 -; CHECK-NEXT: br i1 [[TMP7]], label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; CHECK-NEXT: br i1 false, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] ; CHECK: [[PRED_STORE_IF]]: -; CHECK-NEXT: [[TMP8:%.*]] = add i16 [[OFFSET_IDX]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP8]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 9 ; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 0 ; CHECK-NEXT: store i64 [[TMP10]], ptr [[TMP9]], align 1 ; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE]] ; CHECK: [[PRED_STORE_CONTINUE]]: -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP1]], i32 1 -; CHECK-NEXT: br i1 [[TMP11]], label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2]] +; CHECK-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[EXIT:.*]] ; CHECK: [[PRED_STORE_IF1]]: -; CHECK-NEXT: [[TMP12:%.*]] = add i16 [[OFFSET_IDX]], 1 -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 [[TMP12]] +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i64, ptr [[DST]], i16 10 ; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i64> [[WIDE_LOAD]], i32 1 ; CHECK-NEXT: store i64 [[TMP14]], ptr [[TMP13]], align 1 -; CHECK-NEXT: br label %[[PRED_STORE_CONTINUE2]] -; CHECK: [[PRED_STORE_CONTINUE2]]: -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i16> [[VEC_IND]], splat (i16 2) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br [[EXIT:label %.*]] -; CHECK: [[SCALAR_PH:.*:]] +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: br label %[[SCALAR_PH:.*]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: br label %[[EXIT1:.*]] +; CHECK: [[EXIT1]]: +; CHECK-NEXT: ret void ; entry: br label %loop.header diff --git a/llvm/test/Transforms/LoopVectorize/reduction-minmax-users-and-predicated.ll b/llvm/test/Transforms/LoopVectorize/reduction-minmax-users-and-predicated.ll index c9cc8060ff498..7119728d493d3 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction-minmax-users-and-predicated.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction-minmax-users-and-predicated.ll @@ -48,57 +48,43 @@ define i32 @chained_smax(i32 %x, ptr %src) { ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE6:.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i8> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE6]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP26:%.*]], %[[PRED_LOAD_CONTINUE6]] ] -; CHECK-NEXT: [[TMP0:%.*]] = icmp ule <4 x i8> [[VEC_IND]], splat (i8 1) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[BROADCAST_SPLAT]], <4 x i32> [[VEC_PHI]]) -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP0]], i32 0 -; CHECK-NEXT: br i1 [[TMP2]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[BROADCAST_SPLAT]], <4 x i32> zeroinitializer) +; CHECK-NEXT: br i1 true, label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] ; CHECK: [[PRED_LOAD_IF]]: -; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 0 ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 ; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> poison, i32 [[TMP5]], i32 0 ; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]] ; CHECK: [[PRED_LOAD_CONTINUE]]: ; CHECK-NEXT: [[TMP7:%.*]] = phi <4 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP6]], %[[PRED_LOAD_IF]] ] -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP0]], i32 1 -; CHECK-NEXT: br i1 [[TMP8]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2:.*]] +; CHECK-NEXT: br i1 true, label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2:.*]] ; CHECK: [[PRED_LOAD_IF1]]: -; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 1 ; CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4 ; CHECK-NEXT: [[TMP12:%.*]] = insertelement <4 x i32> [[TMP7]], i32 [[TMP11]], i32 1 ; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]] ; CHECK: [[PRED_LOAD_CONTINUE2]]: ; CHECK-NEXT: [[TMP13:%.*]] = phi <4 x i32> [ [[TMP7]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP12]], %[[PRED_LOAD_IF1]] ] -; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP0]], i32 2 -; CHECK-NEXT: br i1 [[TMP14]], label %[[PRED_LOAD_IF3:.*]], label %[[PRED_LOAD_CONTINUE4:.*]] +; CHECK-NEXT: br i1 false, label %[[PRED_LOAD_IF3:.*]], label %[[PRED_LOAD_CONTINUE4:.*]] ; CHECK: [[PRED_LOAD_IF3]]: -; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP16:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 2 ; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 ; CHECK-NEXT: [[TMP18:%.*]] = insertelement <4 x i32> [[TMP13]], i32 [[TMP17]], i32 2 ; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE4]] ; CHECK: [[PRED_LOAD_CONTINUE4]]: ; CHECK-NEXT: [[TMP19:%.*]] = phi <4 x i32> [ [[TMP13]], %[[PRED_LOAD_CONTINUE2]] ], [ [[TMP18]], %[[PRED_LOAD_IF3]] ] -; CHECK-NEXT: [[TMP20:%.*]] = extractelement <4 x i1> [[TMP0]], i32 3 -; CHECK-NEXT: br i1 [[TMP20]], label %[[PRED_LOAD_IF5:.*]], label %[[PRED_LOAD_CONTINUE6]] +; CHECK-NEXT: br i1 false, label %[[PRED_LOAD_IF5:.*]], label %[[PRED_LOAD_CONTINUE6:.*]] ; CHECK: [[PRED_LOAD_IF5]]: -; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[INDEX]], 3 -; CHECK-NEXT: [[TMP22:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 [[TMP21]] +; CHECK-NEXT: [[TMP22:%.*]] = getelementptr [3 x i32], ptr [[SRC]], i64 3 ; CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 ; CHECK-NEXT: [[TMP24:%.*]] = insertelement <4 x i32> [[TMP19]], i32 [[TMP23]], i32 3 ; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE6]] ; CHECK: [[PRED_LOAD_CONTINUE6]]: -; CHECK-NEXT: [[TMP25:%.*]] = phi <4 x i32> [ [[TMP19]], %[[PRED_LOAD_CONTINUE4]] ], [ [[TMP24]], %[[PRED_LOAD_IF5]] ] -; CHECK-NEXT: [[TMP26]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[TMP25]], <4 x i32> [[TMP1]]) -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i8> [[VEC_IND]], splat (i8 4) -; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[TMP20:%.*]] = phi <4 x i32> [ [[TMP19]], %[[PRED_LOAD_CONTINUE4]] ], [ [[TMP24]], %[[PRED_LOAD_IF5]] ] +; CHECK-NEXT: [[TMP21:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[TMP20]], <4 x i32> [[TMP1]]) +; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: [[TMP27:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP26]], <4 x i32> [[VEC_PHI]] +; CHECK-NEXT: [[TMP27:%.*]] = select <4 x i1> , <4 x i32> [[TMP21]], <4 x i32> zeroinitializer ; CHECK-NEXT: [[TMP28:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP27]]) ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[EXIT]]: @@ -141,7 +127,7 @@ define void @smax_with_invariant_store_user(ptr noalias %src, ptr %dst, i64 %n) ; CHECK-NEXT: [[TMP2]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP2]]) ; CHECK-NEXT: store i32 [[TMP4]], ptr [[DST]], align 4 @@ -160,7 +146,7 @@ define void @smax_with_invariant_store_user(ptr noalias %src, ptr %dst, i64 %n) ; CHECK-NEXT: store i32 [[MAX_NEXT]], ptr [[DST]], align 4 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret void ; @@ -201,7 +187,7 @@ define void @smax_with_multiple_invariant_store_user_same_addr(ptr noalias %src, ; CHECK-NEXT: [[TMP2]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP2]]) ; CHECK-NEXT: store i32 [[TMP4]], ptr [[DST]], align 4 @@ -221,7 +207,7 @@ define void @smax_with_multiple_invariant_store_user_same_addr(ptr noalias %src, ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: store i32 [[MAX_NEXT]], ptr [[DST]], align 4 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret void ; @@ -301,7 +287,7 @@ define void @smax_with_multiple_invariant_store_user_same_addr3(ptr noalias %src ; CHECK-NEXT: [[TMP2]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP2]]) ; CHECK-NEXT: store i32 [[TMP4]], ptr [[DST]], align 4 @@ -321,7 +307,7 @@ define void @smax_with_multiple_invariant_store_user_same_addr3(ptr noalias %src ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: store i32 [[MAX_NEXT]], ptr [[DST]], align 4 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret void ; @@ -478,7 +464,7 @@ define i32 @test_predicated_smin(ptr %src) { ; CHECK-NEXT: [[PREDPHI]] = select <4 x i1> [[TMP1]], <4 x i32> [[TMP4]], <4 x i32> [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 112 -; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[PREDPHI]]) ; CHECK-NEXT: br label %[[EXIT:.*]] @@ -545,7 +531,7 @@ define i32 @smax_reduction_multiple_incoming(ptr %src, i32 %n, i1 %cond) { ; CHECK-NEXT: [[TMP5]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 ; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP1]], [[N_VEC]] @@ -562,7 +548,7 @@ define i32 @smax_reduction_multiple_incoming(ptr %src, i32 %n, i1 %cond) { ; CHECK-NEXT: [[MAX_NEXT]] = tail call i32 @llvm.smax.i32(i32 [[MAX]], i32 [[L]]) ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP11:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP10:![0-9]+]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi i32 [ [[MAX_NEXT]], %[[LOOP_HEADER]] ], [ [[TMP7]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[MAX_NEXT_LCSSA]] diff --git a/llvm/test/Transforms/LoopVectorize/single-early-exit-cond-poison.ll b/llvm/test/Transforms/LoopVectorize/single-early-exit-cond-poison.ll index 97d57a0cf83a0..3b7a0d348fbfb 100644 --- a/llvm/test/Transforms/LoopVectorize/single-early-exit-cond-poison.ll +++ b/llvm/test/Transforms/LoopVectorize/single-early-exit-cond-poison.ll @@ -26,6 +26,8 @@ define noundef i32 @f(i32 noundef %g) { ; VF4IC2-NEXT: [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP6]]) ; VF4IC2-NEXT: br i1 [[TMP7]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF4IC2: [[MIDDLE_BLOCK]]: +; VF4IC2-NEXT: br label %[[MIDDLE_BLOCK1:.*]] +; VF4IC2: [[MIDDLE_BLOCK1]]: ; VF4IC2-NEXT: [[TMP8:%.*]] = extractelement <4 x i32> [[TMP3]], i32 3 ; VF4IC2-NEXT: br label %[[RETURN:.*]] ; VF4IC2: [[VECTOR_EARLY_EXIT]]: @@ -38,7 +40,7 @@ define noundef i32 @f(i32 noundef %g) { ; VF4IC2-NEXT: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32 ; VF4IC2-NEXT: br label %[[RETURN]] ; VF4IC2: [[RETURN]]: -; VF4IC2-NEXT: [[RES:%.*]] = phi i32 [ [[TMP8]], %[[MIDDLE_BLOCK]] ], [ [[TMP15]], %[[VECTOR_EARLY_EXIT]] ] +; VF4IC2-NEXT: [[RES:%.*]] = phi i32 [ [[TMP8]], %[[MIDDLE_BLOCK1]] ], [ [[TMP15]], %[[VECTOR_EARLY_EXIT]] ] ; VF4IC2-NEXT: ret i32 [[RES]] ; ; VF8IC1-LABEL: define noundef i32 @f( @@ -56,6 +58,8 @@ define noundef i32 @f(i32 noundef %g) { ; VF8IC1-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP8]]) ; VF8IC1-NEXT: br i1 [[TMP3]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF8IC1: [[MIDDLE_BLOCK]]: +; VF8IC1-NEXT: br label %[[MIDDLE_BLOCK1:.*]] +; VF8IC1: [[MIDDLE_BLOCK1]]: ; VF8IC1-NEXT: [[TMP4:%.*]] = extractelement <8 x i32> [[TMP1]], i32 7 ; VF8IC1-NEXT: br label %[[RETURN:.*]] ; VF8IC1: [[VECTOR_EARLY_EXIT]]: @@ -63,7 +67,7 @@ define noundef i32 @f(i32 noundef %g) { ; VF8IC1-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 ; VF8IC1-NEXT: br label %[[RETURN]] ; VF8IC1: [[RETURN]]: -; VF8IC1-NEXT: [[RES:%.*]] = phi i32 [ [[TMP4]], %[[MIDDLE_BLOCK]] ], [ [[TMP6]], %[[VECTOR_EARLY_EXIT]] ] +; VF8IC1-NEXT: [[RES:%.*]] = phi i32 [ [[TMP4]], %[[MIDDLE_BLOCK1]] ], [ [[TMP6]], %[[VECTOR_EARLY_EXIT]] ] ; VF8IC1-NEXT: ret i32 [[RES]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination-early-exit.ll b/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination-early-exit.ll index b93215035cebf..1857b5797a5db 100644 --- a/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination-early-exit.ll +++ b/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination-early-exit.ll @@ -53,10 +53,12 @@ define i8 @test_early_exit_max_tc_less_than_16(ptr dereferenceable(16) %A) nosyn ; VF8UF2-NEXT: br i1 [[TMP4]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF8UF2: [[MIDDLE_BLOCK]]: ; VF8UF2-NEXT: br label %[[EXIT:.*]] -; VF8UF2: [[VECTOR_EARLY_EXIT]]: -; VF8UF2-NEXT: br label %[[EXIT]] ; VF8UF2: [[EXIT]]: -; VF8UF2-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[MIDDLE_BLOCK]] ] +; VF8UF2-NEXT: br label %[[EXIT1:.*]] +; VF8UF2: [[VECTOR_EARLY_EXIT]]: +; VF8UF2-NEXT: br label %[[EXIT1]] +; VF8UF2: [[EXIT1]]: +; VF8UF2-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[EXIT]] ] ; VF8UF2-NEXT: ret i8 [[RES]] ; ; VF16UF1-LABEL: define i8 @test_early_exit_max_tc_less_than_16( @@ -73,10 +75,12 @@ define i8 @test_early_exit_max_tc_less_than_16(ptr dereferenceable(16) %A) nosyn ; VF16UF1-NEXT: br i1 [[TMP2]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF16UF1: [[MIDDLE_BLOCK]]: ; VF16UF1-NEXT: br label %[[EXIT:.*]] -; VF16UF1: [[VECTOR_EARLY_EXIT]]: -; VF16UF1-NEXT: br label %[[EXIT]] ; VF16UF1: [[EXIT]]: -; VF16UF1-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[MIDDLE_BLOCK]] ] +; VF16UF1-NEXT: br label %[[EXIT1:.*]] +; VF16UF1: [[VECTOR_EARLY_EXIT]]: +; VF16UF1-NEXT: br label %[[EXIT1]] +; VF16UF1: [[EXIT1]]: +; VF16UF1-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[EXIT]] ] ; VF16UF1-NEXT: ret i8 [[RES]] ; entry: @@ -147,6 +151,8 @@ define i64 @test_early_exit_max_tc_less_than_16_with_iv_used_outside(ptr derefer ; VF8UF2-NEXT: br i1 [[TMP4]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF8UF2: [[MIDDLE_BLOCK]]: ; VF8UF2-NEXT: br label %[[EXIT:.*]] +; VF8UF2: [[EXIT]]: +; VF8UF2-NEXT: br label %[[EXIT1:.*]] ; VF8UF2: [[VECTOR_EARLY_EXIT]]: ; VF8UF2-NEXT: [[TMP5:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1> [[TMP2]], i1 false) ; VF8UF2-NEXT: [[TMP7:%.*]] = add i64 8, [[TMP5]] @@ -154,9 +160,9 @@ define i64 @test_early_exit_max_tc_less_than_16_with_iv_used_outside(ptr derefer ; VF8UF2-NEXT: [[TMP9:%.*]] = add i64 0, [[TMP8]] ; VF8UF2-NEXT: [[TMP10:%.*]] = icmp ne i64 [[TMP8]], 8 ; VF8UF2-NEXT: [[TMP11:%.*]] = select i1 [[TMP10]], i64 [[TMP9]], i64 [[TMP7]] -; VF8UF2-NEXT: br label %[[EXIT]] -; VF8UF2: [[EXIT]]: -; VF8UF2-NEXT: [[RES:%.*]] = phi i64 [ [[TMP11]], %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[MIDDLE_BLOCK]] ] +; VF8UF2-NEXT: br label %[[EXIT1]] +; VF8UF2: [[EXIT1]]: +; VF8UF2-NEXT: [[RES:%.*]] = phi i64 [ [[TMP11]], %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[EXIT]] ] ; VF8UF2-NEXT: ret i64 [[RES]] ; ; VF16UF1-LABEL: define i64 @test_early_exit_max_tc_less_than_16_with_iv_used_outside( @@ -173,11 +179,13 @@ define i64 @test_early_exit_max_tc_less_than_16_with_iv_used_outside(ptr derefer ; VF16UF1-NEXT: br i1 [[TMP2]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF16UF1: [[MIDDLE_BLOCK]]: ; VF16UF1-NEXT: br label %[[EXIT:.*]] +; VF16UF1: [[EXIT]]: +; VF16UF1-NEXT: br label %[[EXIT1:.*]] ; VF16UF1: [[VECTOR_EARLY_EXIT]]: ; VF16UF1-NEXT: [[FIRST_ACTIVE_LANE:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v16i1(<16 x i1> [[TMP3]], i1 false) -; VF16UF1-NEXT: br label %[[EXIT]] -; VF16UF1: [[EXIT]]: -; VF16UF1-NEXT: [[RES:%.*]] = phi i64 [ [[FIRST_ACTIVE_LANE]], %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[MIDDLE_BLOCK]] ] +; VF16UF1-NEXT: br label %[[EXIT1]] +; VF16UF1: [[EXIT1]]: +; VF16UF1-NEXT: [[RES:%.*]] = phi i64 [ [[FIRST_ACTIVE_LANE]], %[[VECTOR_EARLY_EXIT]] ], [ 1, %[[EXIT]] ] ; VF16UF1-NEXT: ret i64 [[RES]] ; entry: @@ -258,22 +266,24 @@ define i8 @test_early_exit_max_vector_tc_eq_16(ptr dereferenceable(17) %A) nosyn ; VF8UF2-NEXT: br i1 [[TMP5]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF8UF2: [[MIDDLE_BLOCK]]: ; VF8UF2-NEXT: br label %[[SCALAR_PH:.*]] -; VF8UF2: [[VECTOR_EARLY_EXIT]]: -; VF8UF2-NEXT: br label %[[EXIT:.*]] ; VF8UF2: [[SCALAR_PH]]: +; VF8UF2-NEXT: br label %[[EXIT:.*]] +; VF8UF2: [[VECTOR_EARLY_EXIT]]: ; VF8UF2-NEXT: br label %[[LOOP_HEADER:.*]] -; VF8UF2: [[LOOP_HEADER]]: -; VF8UF2-NEXT: [[IV:%.*]] = phi i64 [ 16, %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; VF8UF2: [[EXIT]]: +; VF8UF2-NEXT: br label %[[LOOP_HEADER1:.*]] +; VF8UF2: [[LOOP_HEADER1]]: +; VF8UF2-NEXT: [[IV:%.*]] = phi i64 [ 16, %[[EXIT]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] ; VF8UF2-NEXT: [[P_SRC:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[IV]] ; VF8UF2-NEXT: [[L:%.*]] = load i8, ptr [[P_SRC]], align 1 ; VF8UF2-NEXT: [[C:%.*]] = icmp eq i8 [[L]], 0 -; VF8UF2-NEXT: br i1 [[C]], label %[[EXIT]], label %[[LOOP_LATCH]] +; VF8UF2-NEXT: br i1 [[C]], label %[[LOOP_HEADER]], label %[[LOOP_LATCH]] ; VF8UF2: [[LOOP_LATCH]]: ; VF8UF2-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; VF8UF2-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 17 -; VF8UF2-NEXT: br i1 [[CMP]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP0:![0-9]+]] -; VF8UF2: [[EXIT]]: -; VF8UF2-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[LOOP_HEADER]] ], [ 1, %[[LOOP_LATCH]] ], [ 0, %[[VECTOR_EARLY_EXIT]] ] +; VF8UF2-NEXT: br i1 [[CMP]], label %[[LOOP_HEADER]], label %[[LOOP_HEADER1]], !llvm.loop [[LOOP0:![0-9]+]] +; VF8UF2: [[LOOP_HEADER]]: +; VF8UF2-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[LOOP_HEADER1]] ], [ 1, %[[LOOP_LATCH]] ], [ 0, %[[VECTOR_EARLY_EXIT]] ] ; VF8UF2-NEXT: ret i8 [[RES]] ; ; VF16UF1-LABEL: define i8 @test_early_exit_max_vector_tc_eq_16( @@ -290,22 +300,24 @@ define i8 @test_early_exit_max_vector_tc_eq_16(ptr dereferenceable(17) %A) nosyn ; VF16UF1-NEXT: br i1 [[TMP2]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]] ; VF16UF1: [[MIDDLE_BLOCK]]: ; VF16UF1-NEXT: br label %[[SCALAR_PH:.*]] -; VF16UF1: [[VECTOR_EARLY_EXIT]]: -; VF16UF1-NEXT: br label %[[EXIT:.*]] ; VF16UF1: [[SCALAR_PH]]: +; VF16UF1-NEXT: br label %[[EXIT:.*]] +; VF16UF1: [[VECTOR_EARLY_EXIT]]: ; VF16UF1-NEXT: br label %[[LOOP_HEADER:.*]] -; VF16UF1: [[LOOP_HEADER]]: -; VF16UF1-NEXT: [[IV:%.*]] = phi i64 [ 16, %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] +; VF16UF1: [[EXIT]]: +; VF16UF1-NEXT: br label %[[LOOP_HEADER1:.*]] +; VF16UF1: [[LOOP_HEADER1]]: +; VF16UF1-NEXT: [[IV:%.*]] = phi i64 [ 16, %[[EXIT]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] ; VF16UF1-NEXT: [[P_SRC:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[IV]] ; VF16UF1-NEXT: [[L:%.*]] = load i8, ptr [[P_SRC]], align 1 ; VF16UF1-NEXT: [[C:%.*]] = icmp eq i8 [[L]], 0 -; VF16UF1-NEXT: br i1 [[C]], label %[[EXIT]], label %[[LOOP_LATCH]] +; VF16UF1-NEXT: br i1 [[C]], label %[[LOOP_HEADER]], label %[[LOOP_LATCH]] ; VF16UF1: [[LOOP_LATCH]]: ; VF16UF1-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; VF16UF1-NEXT: [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], 17 -; VF16UF1-NEXT: br i1 [[CMP]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP0:![0-9]+]] -; VF16UF1: [[EXIT]]: -; VF16UF1-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[LOOP_HEADER]] ], [ 1, %[[LOOP_LATCH]] ], [ 0, %[[VECTOR_EARLY_EXIT]] ] +; VF16UF1-NEXT: br i1 [[CMP]], label %[[LOOP_HEADER]], label %[[LOOP_HEADER1]], !llvm.loop [[LOOP0:![0-9]+]] +; VF16UF1: [[LOOP_HEADER]]: +; VF16UF1-NEXT: [[RES:%.*]] = phi i8 [ 0, %[[LOOP_HEADER1]] ], [ 1, %[[LOOP_LATCH]] ], [ 0, %[[VECTOR_EARLY_EXIT]] ] ; VF16UF1-NEXT: ret i8 [[RES]] ; entry: @@ -368,28 +380,22 @@ define i1 @test_early_exit_max_tc_less_than_16_non_canonical_iv(ptr dereferencea ; VF8UF2: [[VECTOR_PH]]: ; VF8UF2-NEXT: br label %[[VECTOR_BODY:.*]] ; VF8UF2: [[VECTOR_BODY]]: -; VF8UF2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY_INTERIM:.*]] ] -; VF8UF2-NEXT: [[VEC_IND:%.*]] = phi <8 x i64> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY_INTERIM]] ] -; VF8UF2-NEXT: [[STEP_ADD:%.*]] = add <8 x i64> [[VEC_IND]], splat (i64 8) -; VF8UF2-NEXT: [[OFFSET_IDX:%.*]] = add i64 2, [[INDEX]] -; VF8UF2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[OFFSET_IDX]] +; VF8UF2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 2 ; VF8UF2-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 ; VF8UF2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP0]], align 1 ; VF8UF2-NEXT: [[WIDE_LOAD1:%.*]] = load <8 x i8>, ptr [[TMP1]], align 1 ; VF8UF2-NEXT: [[TMP4:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer ; VF8UF2-NEXT: [[TMP5:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD1]], zeroinitializer -; VF8UF2-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; VF8UF2-NEXT: [[TMP6:%.*]] = freeze <8 x i1> [[TMP4]] ; VF8UF2-NEXT: [[TMP7:%.*]] = freeze <8 x i1> [[TMP5]] ; VF8UF2-NEXT: [[TMP8:%.*]] = or <8 x i1> [[TMP6]], [[TMP7]] ; VF8UF2-NEXT: [[TMP9:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP8]]) -; VF8UF2-NEXT: [[VEC_IND_NEXT]] = add nsw <8 x i64> [[STEP_ADD]], splat (i64 8) -; VF8UF2-NEXT: br i1 [[TMP9]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[VECTOR_BODY_INTERIM]] +; VF8UF2-NEXT: br i1 [[TMP9]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[VECTOR_BODY_INTERIM:.*]] ; VF8UF2: [[VECTOR_BODY_INTERIM]]: -; VF8UF2-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; VF8UF2-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; VF8UF2: [[MIDDLE_BLOCK]]: ; VF8UF2-NEXT: [[TMP10:%.*]] = zext <8 x i8> [[WIDE_LOAD1]] to <8 x i64> -; VF8UF2-NEXT: [[TMP3:%.*]] = icmp eq <8 x i64> [[TMP10]], [[STEP_ADD]] +; VF8UF2-NEXT: [[TMP3:%.*]] = icmp eq <8 x i64> [[TMP10]], ; VF8UF2-NEXT: [[TMP12:%.*]] = extractelement <8 x i1> [[TMP3]], i32 7 ; VF8UF2-NEXT: br label %[[EXIT:.*]] ; VF8UF2: [[VECTOR_EARLY_EXIT]]: @@ -405,22 +411,17 @@ define i1 @test_early_exit_max_tc_less_than_16_non_canonical_iv(ptr dereferencea ; VF16UF1: [[VECTOR_PH]]: ; VF16UF1-NEXT: br label %[[VECTOR_BODY:.*]] ; VF16UF1: [[VECTOR_BODY]]: -; VF16UF1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY_INTERIM:.*]] ] -; VF16UF1-NEXT: [[VEC_IND:%.*]] = phi <16 x i64> [ , %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY_INTERIM]] ] -; VF16UF1-NEXT: [[OFFSET_IDX:%.*]] = add i64 2, [[INDEX]] -; VF16UF1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[OFFSET_IDX]] +; VF16UF1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 2 ; VF16UF1-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i8>, ptr [[TMP0]], align 1 ; VF16UF1-NEXT: [[TMP3:%.*]] = icmp eq <16 x i8> [[WIDE_LOAD]], zeroinitializer -; VF16UF1-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; VF16UF1-NEXT: [[TMP4:%.*]] = freeze <16 x i1> [[TMP3]] ; VF16UF1-NEXT: [[TMP5:%.*]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[TMP4]]) -; VF16UF1-NEXT: [[VEC_IND_NEXT]] = add nsw <16 x i64> [[VEC_IND]], splat (i64 16) -; VF16UF1-NEXT: br i1 [[TMP5]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[VECTOR_BODY_INTERIM]] +; VF16UF1-NEXT: br i1 [[TMP5]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[VECTOR_BODY_INTERIM:.*]] ; VF16UF1: [[VECTOR_BODY_INTERIM]]: -; VF16UF1-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] +; VF16UF1-NEXT: br label %[[MIDDLE_BLOCK:.*]] ; VF16UF1: [[MIDDLE_BLOCK]]: ; VF16UF1-NEXT: [[TMP6:%.*]] = zext <16 x i8> [[WIDE_LOAD]] to <16 x i64> -; VF16UF1-NEXT: [[TMP2:%.*]] = icmp eq <16 x i64> [[TMP6]], [[VEC_IND]] +; VF16UF1-NEXT: [[TMP2:%.*]] = icmp eq <16 x i64> [[TMP6]], ; VF16UF1-NEXT: [[TMP8:%.*]] = extractelement <16 x i1> [[TMP2]], i32 15 ; VF16UF1-NEXT: br label %[[EXIT:.*]] ; VF16UF1: [[VECTOR_EARLY_EXIT]]: diff --git a/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination.ll b/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination.ll index 5da6fc3179043..02846aba50f72 100644 --- a/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination.ll +++ b/llvm/test/Transforms/LoopVectorize/vector-loop-backedge-elimination.ll @@ -1211,6 +1211,272 @@ loop: exit: ret void } + +; Test that a first-order recurrence with a single vector iteration (where the +; vector loop backedge is removed) does not crash. +define void @first_order_recurrence_single_vector_iteration(ptr noalias %pkt, ptr noalias %dst) { +; VF8UF1-LABEL: define void @first_order_recurrence_single_vector_iteration( +; VF8UF1-SAME: ptr noalias [[PKT:%.*]], ptr noalias [[DST:%.*]]) { +; VF8UF1-NEXT: [[ENTRY:.*:]] +; VF8UF1-NEXT: br label %[[VECTOR_PH:.*]] +; VF8UF1: [[VECTOR_PH]]: +; VF8UF1-NEXT: br label %[[VECTOR_BODY:.*]] +; VF8UF1: [[VECTOR_BODY]]: +; VF8UF1-NEXT: [[TMP0:%.*]] = load i8, ptr [[PKT]], align 1 +; VF8UF1-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i8> poison, i8 [[TMP0]], i64 0 +; VF8UF1-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i8> [[BROADCAST_SPLATINSERT]], <8 x i8> poison, <8 x i32> zeroinitializer +; VF8UF1-NEXT: [[TMP1:%.*]] = shufflevector <8 x i8> zeroinitializer, <8 x i8> [[BROADCAST_SPLAT]], <8 x i32> +; VF8UF1-NEXT: [[TMP2:%.*]] = extractelement <8 x i8> [[TMP1]], i32 7 +; VF8UF1-NEXT: store i8 [[TMP2]], ptr [[DST]], align 1 +; VF8UF1-NEXT: br label %[[MIDDLE_BLOCK:.*]] +; VF8UF1: [[MIDDLE_BLOCK]]: +; VF8UF1-NEXT: br label %[[EXIT:.*]] +; VF8UF1: [[EXIT]]: +; VF8UF1-NEXT: ret void +; +; VF8UF2-LABEL: define void @first_order_recurrence_single_vector_iteration( +; VF8UF2-SAME: ptr noalias [[PKT:%.*]], ptr noalias [[DST:%.*]]) { +; VF8UF2-NEXT: [[ENTRY:.*:]] +; VF8UF2-NEXT: br label %[[VECTOR_PH:.*]] +; VF8UF2: [[VECTOR_PH]]: +; VF8UF2-NEXT: br label %[[VECTOR_BODY:.*]] +; VF8UF2: [[VECTOR_BODY]]: +; VF8UF2-NEXT: [[TMP0:%.*]] = load i8, ptr [[PKT]], align 1 +; VF8UF2-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i8> poison, i8 [[TMP0]], i64 0 +; VF8UF2-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i8> [[BROADCAST_SPLATINSERT]], <8 x i8> poison, <8 x i32> zeroinitializer +; VF8UF2-NEXT: [[TMP1:%.*]] = shufflevector <8 x i8> zeroinitializer, <8 x i8> [[BROADCAST_SPLAT]], <8 x i32> +; VF8UF2-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[BROADCAST_SPLAT]], <8 x i8> [[BROADCAST_SPLAT]], <8 x i32> +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; VF8UF2: [[PRED_STORE_IF]]: +; VF8UF2-NEXT: [[TMP3:%.*]] = extractelement <8 x i8> [[TMP1]], i32 0 +; VF8UF2-NEXT: store i8 [[TMP3]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE]] +; VF8UF2: [[PRED_STORE_CONTINUE]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2:.*]] +; VF8UF2: [[PRED_STORE_IF1]]: +; VF8UF2-NEXT: [[TMP4:%.*]] = extractelement <8 x i8> [[TMP1]], i32 1 +; VF8UF2-NEXT: store i8 [[TMP4]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE2]] +; VF8UF2: [[PRED_STORE_CONTINUE2]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF3:.*]], label %[[PRED_STORE_CONTINUE4:.*]] +; VF8UF2: [[PRED_STORE_IF3]]: +; VF8UF2-NEXT: [[TMP5:%.*]] = extractelement <8 x i8> [[TMP1]], i32 2 +; VF8UF2-NEXT: store i8 [[TMP5]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE4]] +; VF8UF2: [[PRED_STORE_CONTINUE4]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF5:.*]], label %[[PRED_STORE_CONTINUE6:.*]] +; VF8UF2: [[PRED_STORE_IF5]]: +; VF8UF2-NEXT: [[TMP6:%.*]] = extractelement <8 x i8> [[TMP1]], i32 3 +; VF8UF2-NEXT: store i8 [[TMP6]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE6]] +; VF8UF2: [[PRED_STORE_CONTINUE6]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF7:.*]], label %[[PRED_STORE_CONTINUE8:.*]] +; VF8UF2: [[PRED_STORE_IF7]]: +; VF8UF2-NEXT: [[TMP7:%.*]] = extractelement <8 x i8> [[TMP1]], i32 4 +; VF8UF2-NEXT: store i8 [[TMP7]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE8]] +; VF8UF2: [[PRED_STORE_CONTINUE8]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF9:.*]], label %[[PRED_STORE_CONTINUE10:.*]] +; VF8UF2: [[PRED_STORE_IF9]]: +; VF8UF2-NEXT: [[TMP8:%.*]] = extractelement <8 x i8> [[TMP1]], i32 5 +; VF8UF2-NEXT: store i8 [[TMP8]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE10]] +; VF8UF2: [[PRED_STORE_CONTINUE10]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF11:.*]], label %[[PRED_STORE_CONTINUE12:.*]] +; VF8UF2: [[PRED_STORE_IF11]]: +; VF8UF2-NEXT: [[TMP9:%.*]] = extractelement <8 x i8> [[TMP1]], i32 6 +; VF8UF2-NEXT: store i8 [[TMP9]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE12]] +; VF8UF2: [[PRED_STORE_CONTINUE12]]: +; VF8UF2-NEXT: br i1 true, label %[[PRED_STORE_IF13:.*]], label %[[PRED_STORE_CONTINUE14:.*]] +; VF8UF2: [[PRED_STORE_IF13]]: +; VF8UF2-NEXT: [[TMP10:%.*]] = extractelement <8 x i8> [[TMP1]], i32 7 +; VF8UF2-NEXT: store i8 [[TMP10]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE14]] +; VF8UF2: [[PRED_STORE_CONTINUE14]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF15:.*]], label %[[PRED_STORE_CONTINUE16:.*]] +; VF8UF2: [[PRED_STORE_IF15]]: +; VF8UF2-NEXT: [[TMP11:%.*]] = extractelement <8 x i8> [[TMP2]], i32 0 +; VF8UF2-NEXT: store i8 [[TMP11]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE16]] +; VF8UF2: [[PRED_STORE_CONTINUE16]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF17:.*]], label %[[PRED_STORE_CONTINUE18:.*]] +; VF8UF2: [[PRED_STORE_IF17]]: +; VF8UF2-NEXT: [[TMP12:%.*]] = extractelement <8 x i8> [[TMP2]], i32 1 +; VF8UF2-NEXT: store i8 [[TMP12]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE18]] +; VF8UF2: [[PRED_STORE_CONTINUE18]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF19:.*]], label %[[PRED_STORE_CONTINUE20:.*]] +; VF8UF2: [[PRED_STORE_IF19]]: +; VF8UF2-NEXT: [[TMP13:%.*]] = extractelement <8 x i8> [[TMP2]], i32 2 +; VF8UF2-NEXT: store i8 [[TMP13]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE20]] +; VF8UF2: [[PRED_STORE_CONTINUE20]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF21:.*]], label %[[PRED_STORE_CONTINUE22:.*]] +; VF8UF2: [[PRED_STORE_IF21]]: +; VF8UF2-NEXT: [[TMP14:%.*]] = extractelement <8 x i8> [[TMP2]], i32 3 +; VF8UF2-NEXT: store i8 [[TMP14]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE22]] +; VF8UF2: [[PRED_STORE_CONTINUE22]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF23:.*]], label %[[PRED_STORE_CONTINUE24:.*]] +; VF8UF2: [[PRED_STORE_IF23]]: +; VF8UF2-NEXT: [[TMP15:%.*]] = extractelement <8 x i8> [[TMP2]], i32 4 +; VF8UF2-NEXT: store i8 [[TMP15]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE24]] +; VF8UF2: [[PRED_STORE_CONTINUE24]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF25:.*]], label %[[PRED_STORE_CONTINUE26:.*]] +; VF8UF2: [[PRED_STORE_IF25]]: +; VF8UF2-NEXT: [[TMP16:%.*]] = extractelement <8 x i8> [[TMP2]], i32 5 +; VF8UF2-NEXT: store i8 [[TMP16]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE26]] +; VF8UF2: [[PRED_STORE_CONTINUE26]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF27:.*]], label %[[PRED_STORE_CONTINUE28:.*]] +; VF8UF2: [[PRED_STORE_IF27]]: +; VF8UF2-NEXT: [[TMP17:%.*]] = extractelement <8 x i8> [[TMP2]], i32 6 +; VF8UF2-NEXT: store i8 [[TMP17]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE28]] +; VF8UF2: [[PRED_STORE_CONTINUE28]]: +; VF8UF2-NEXT: br i1 false, label %[[PRED_STORE_IF29:.*]], label %[[PRED_STORE_CONTINUE30:.*]] +; VF8UF2: [[PRED_STORE_IF29]]: +; VF8UF2-NEXT: [[TMP18:%.*]] = extractelement <8 x i8> [[TMP2]], i32 7 +; VF8UF2-NEXT: store i8 [[TMP18]], ptr [[DST]], align 1 +; VF8UF2-NEXT: br label %[[PRED_STORE_CONTINUE30]] +; VF8UF2: [[PRED_STORE_CONTINUE30]]: +; VF8UF2-NEXT: br label %[[MIDDLE_BLOCK:.*]] +; VF8UF2: [[MIDDLE_BLOCK]]: +; VF8UF2-NEXT: br label %[[EXIT:.*]] +; VF8UF2: [[EXIT]]: +; VF8UF2-NEXT: ret void +; +; VF16UF1-LABEL: define void @first_order_recurrence_single_vector_iteration( +; VF16UF1-SAME: ptr noalias [[PKT:%.*]], ptr noalias [[DST:%.*]]) { +; VF16UF1-NEXT: [[ENTRY:.*:]] +; VF16UF1-NEXT: br label %[[VECTOR_PH:.*]] +; VF16UF1: [[VECTOR_PH]]: +; VF16UF1-NEXT: br label %[[VECTOR_BODY:.*]] +; VF16UF1: [[VECTOR_BODY]]: +; VF16UF1-NEXT: [[TMP0:%.*]] = load i8, ptr [[PKT]], align 1 +; VF16UF1-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <16 x i8> poison, i8 [[TMP0]], i64 0 +; VF16UF1-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <16 x i8> [[BROADCAST_SPLATINSERT]], <16 x i8> poison, <16 x i32> zeroinitializer +; VF16UF1-NEXT: [[TMP1:%.*]] = shufflevector <16 x i8> zeroinitializer, <16 x i8> [[BROADCAST_SPLAT]], <16 x i32> +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF:.*]], label %[[PRED_STORE_CONTINUE:.*]] +; VF16UF1: [[PRED_STORE_IF]]: +; VF16UF1-NEXT: [[TMP2:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0 +; VF16UF1-NEXT: store i8 [[TMP2]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE]] +; VF16UF1: [[PRED_STORE_CONTINUE]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF1:.*]], label %[[PRED_STORE_CONTINUE2:.*]] +; VF16UF1: [[PRED_STORE_IF1]]: +; VF16UF1-NEXT: [[TMP3:%.*]] = extractelement <16 x i8> [[TMP1]], i32 1 +; VF16UF1-NEXT: store i8 [[TMP3]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE2]] +; VF16UF1: [[PRED_STORE_CONTINUE2]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF3:.*]], label %[[PRED_STORE_CONTINUE4:.*]] +; VF16UF1: [[PRED_STORE_IF3]]: +; VF16UF1-NEXT: [[TMP4:%.*]] = extractelement <16 x i8> [[TMP1]], i32 2 +; VF16UF1-NEXT: store i8 [[TMP4]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE4]] +; VF16UF1: [[PRED_STORE_CONTINUE4]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF5:.*]], label %[[PRED_STORE_CONTINUE6:.*]] +; VF16UF1: [[PRED_STORE_IF5]]: +; VF16UF1-NEXT: [[TMP5:%.*]] = extractelement <16 x i8> [[TMP1]], i32 3 +; VF16UF1-NEXT: store i8 [[TMP5]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE6]] +; VF16UF1: [[PRED_STORE_CONTINUE6]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF7:.*]], label %[[PRED_STORE_CONTINUE8:.*]] +; VF16UF1: [[PRED_STORE_IF7]]: +; VF16UF1-NEXT: [[TMP6:%.*]] = extractelement <16 x i8> [[TMP1]], i32 4 +; VF16UF1-NEXT: store i8 [[TMP6]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE8]] +; VF16UF1: [[PRED_STORE_CONTINUE8]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF9:.*]], label %[[PRED_STORE_CONTINUE10:.*]] +; VF16UF1: [[PRED_STORE_IF9]]: +; VF16UF1-NEXT: [[TMP7:%.*]] = extractelement <16 x i8> [[TMP1]], i32 5 +; VF16UF1-NEXT: store i8 [[TMP7]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE10]] +; VF16UF1: [[PRED_STORE_CONTINUE10]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF11:.*]], label %[[PRED_STORE_CONTINUE12:.*]] +; VF16UF1: [[PRED_STORE_IF11]]: +; VF16UF1-NEXT: [[TMP8:%.*]] = extractelement <16 x i8> [[TMP1]], i32 6 +; VF16UF1-NEXT: store i8 [[TMP8]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE12]] +; VF16UF1: [[PRED_STORE_CONTINUE12]]: +; VF16UF1-NEXT: br i1 true, label %[[PRED_STORE_IF13:.*]], label %[[PRED_STORE_CONTINUE14:.*]] +; VF16UF1: [[PRED_STORE_IF13]]: +; VF16UF1-NEXT: [[TMP9:%.*]] = extractelement <16 x i8> [[TMP1]], i32 7 +; VF16UF1-NEXT: store i8 [[TMP9]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE14]] +; VF16UF1: [[PRED_STORE_CONTINUE14]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF15:.*]], label %[[PRED_STORE_CONTINUE16:.*]] +; VF16UF1: [[PRED_STORE_IF15]]: +; VF16UF1-NEXT: [[TMP10:%.*]] = extractelement <16 x i8> [[TMP1]], i32 8 +; VF16UF1-NEXT: store i8 [[TMP10]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE16]] +; VF16UF1: [[PRED_STORE_CONTINUE16]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF17:.*]], label %[[PRED_STORE_CONTINUE18:.*]] +; VF16UF1: [[PRED_STORE_IF17]]: +; VF16UF1-NEXT: [[TMP11:%.*]] = extractelement <16 x i8> [[TMP1]], i32 9 +; VF16UF1-NEXT: store i8 [[TMP11]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE18]] +; VF16UF1: [[PRED_STORE_CONTINUE18]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF19:.*]], label %[[PRED_STORE_CONTINUE20:.*]] +; VF16UF1: [[PRED_STORE_IF19]]: +; VF16UF1-NEXT: [[TMP12:%.*]] = extractelement <16 x i8> [[TMP1]], i32 10 +; VF16UF1-NEXT: store i8 [[TMP12]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE20]] +; VF16UF1: [[PRED_STORE_CONTINUE20]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF21:.*]], label %[[PRED_STORE_CONTINUE22:.*]] +; VF16UF1: [[PRED_STORE_IF21]]: +; VF16UF1-NEXT: [[TMP13:%.*]] = extractelement <16 x i8> [[TMP1]], i32 11 +; VF16UF1-NEXT: store i8 [[TMP13]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE22]] +; VF16UF1: [[PRED_STORE_CONTINUE22]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF23:.*]], label %[[PRED_STORE_CONTINUE24:.*]] +; VF16UF1: [[PRED_STORE_IF23]]: +; VF16UF1-NEXT: [[TMP14:%.*]] = extractelement <16 x i8> [[TMP1]], i32 12 +; VF16UF1-NEXT: store i8 [[TMP14]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE24]] +; VF16UF1: [[PRED_STORE_CONTINUE24]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF25:.*]], label %[[PRED_STORE_CONTINUE26:.*]] +; VF16UF1: [[PRED_STORE_IF25]]: +; VF16UF1-NEXT: [[TMP15:%.*]] = extractelement <16 x i8> [[TMP1]], i32 13 +; VF16UF1-NEXT: store i8 [[TMP15]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE26]] +; VF16UF1: [[PRED_STORE_CONTINUE26]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF27:.*]], label %[[PRED_STORE_CONTINUE28:.*]] +; VF16UF1: [[PRED_STORE_IF27]]: +; VF16UF1-NEXT: [[TMP16:%.*]] = extractelement <16 x i8> [[TMP1]], i32 14 +; VF16UF1-NEXT: store i8 [[TMP16]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE28]] +; VF16UF1: [[PRED_STORE_CONTINUE28]]: +; VF16UF1-NEXT: br i1 false, label %[[PRED_STORE_IF29:.*]], label %[[PRED_STORE_CONTINUE30:.*]] +; VF16UF1: [[PRED_STORE_IF29]]: +; VF16UF1-NEXT: [[TMP17:%.*]] = extractelement <16 x i8> [[TMP1]], i32 15 +; VF16UF1-NEXT: store i8 [[TMP17]], ptr [[DST]], align 1 +; VF16UF1-NEXT: br label %[[PRED_STORE_CONTINUE30]] +; VF16UF1: [[PRED_STORE_CONTINUE30]]: +; VF16UF1-NEXT: br label %[[MIDDLE_BLOCK:.*]] +; VF16UF1: [[MIDDLE_BLOCK]]: +; VF16UF1-NEXT: br label %[[EXIT:.*]] +; VF16UF1: [[EXIT]]: +; VF16UF1-NEXT: ret void +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %recur = phi i8 [ 0, %entry ], [ %load, %loop ] + %load = load i8, ptr %pkt, align 1 + store i8 %recur, ptr %dst, align 1 + %iv.next = add i64 %iv, 1 + %cmp = icmp eq i64 %iv, 7 + br i1 %cmp, label %exit, label %loop + +exit: + ret void +} +;. !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ;. ; VF8UF1: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ; VF8UF1: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} From 975dba28633d2f3746a8a370741b17024b0f5f9b Mon Sep 17 00:00:00 2001 From: yonghong-song Date: Fri, 27 Feb 2026 09:09:54 -0800 Subject: [PATCH 03/58] [ThinLTO] Reduce the number of renaming due to promotions (#178587) Currently for thin-lto, the imported static global values (functions, variables, etc) will be promoted/renamed from e.g., foo() to foo.llvm.(). Such a renaming caused difficulties in live patching since function name is changed ([1]). It is possible that some global value names have to be promoted to avoid name collision and linker failure. But in practice, majority of name promotions can be avoided. In [2], the suggestion is that thin-lto pre-link decides whether a particular global value needs name promotion or not. If yes, later on in thinBackend() the name will be promoted. I compiled a particular linux kernel version (latest bpf-next tree) and found 1216 global values with suffix .llvm.. With this patch, the number of promoted functions is 2, 98% reduction from the original kernel build. If some native objects are not participating with LTO, name promotions have to be done to avoid potential linker issues. So the current implementation cannot be on by default. But in certain cases, e.g., linux kernel build, people can enable lld flag --lto-whole-program-visibility to reduce the number of functions like foo.llvm.(). For ThinLTOCodeGenerator.cpp which is used by llvm-lto tool and a few other rare cases, reducing the number of renaming due to promotion, is not implemented as lld flag '-lto-whole-program-visibility' is not supported in ThinLTOCodeGenerator.cpp for now. In summary, this pull request only supports llvm-lto2 style workflow. [1] https://lpc.events/event/19/contributions/2212 [2] https://discourse.llvm.org/t/rfc-avoid-functions-like-foo-llvm-for-kernel-live-patch/89400 --- .../distributed-thin-lto/cfi-devirt.ll | 2 +- .../test/CodeGen/distributed-thin-lto/cfi.ll | 2 +- clang/test/CodeGen/thinlto-funcattr-prop.ll | 4 +- lld/test/ELF/lto/comdat-nodeduplicate.ll | 8 +- llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/IR/ModuleSummaryIndex.h | 21 +++- llvm/include/llvm/IR/ModuleSummaryIndexYAML.h | 14 ++- llvm/include/llvm/LTO/LTO.h | 3 +- .../llvm/Transforms/IPO/WholeProgramDevirt.h | 6 +- .../Transforms/Utils/FunctionImportUtils.h | 3 +- llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 10 +- llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 12 ++- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 4 +- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 + llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/IR/ModuleSummaryIndex.cpp | 2 + llvm/lib/LTO/LTO.cpp | 59 +++++++++-- .../lib/Transforms/IPO/WholeProgramDevirt.cpp | 29 ++++-- .../Transforms/Utils/FunctionImportUtils.cpp | 24 ++++- .../test/Assembler/thinlto-memprof-summary.ll | 24 ++--- .../thinlto-multiple-summaries-for-guid.ll | 4 +- .../Assembler/thinlto-summary-visibility.ll | 6 +- llvm/test/Assembler/thinlto-summary.ll | 60 +++++------ llvm/test/Assembler/thinlto-vtable-summary.ll | 4 +- llvm/test/Bitcode/thinlto-alias.ll | 10 +- ...ction-summary-callgraph-profile-summary.ll | 18 ++-- ...hinlto-function-summary-callgraph-relbf.ll | 2 +- .../thinlto-function-summary-refgraph.ll | 14 +-- .../thinlto-index-disassembled-by-llvm-dis.ll | 2 +- llvm/test/Bitcode/thinlto-type-tests.ll | 12 +-- llvm/test/Bitcode/thinlto-type-vcalls.ll | 24 ++--- .../reduce-promotion-same-file-local-name.ll | 20 ++++ .../ThinLTO/X86/funcattrs-prop-maythrow.ll | 6 +- .../ThinLTO/X86/funcimport_alwaysinline.ll | 2 +- .../ThinLTO/X86/import_callee_declaration.ll | 8 +- llvm/test/ThinLTO/X86/load-store-caching.ll | 4 +- .../ThinLTO/X86/reduce-promotion-devirt.ll | 99 +++++++++++++++++++ .../reduce-promotion-same-file-local-name.ll | 46 +++++++++ .../X86/reduce-promotion-same-local-name.ll | 69 +++++++++++++ llvm/test/ThinLTO/X86/reduce-promotion.ll | 56 +++++++++++ .../Transforms/LowerTypeTests/import-unsat.ll | 1 + .../Inputs/import-indir.yaml | 1 + .../WholeProgramDevirt/import-indir.ll | 2 + 44 files changed, 555 insertions(+), 147 deletions(-) create mode 100644 llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll create mode 100644 llvm/test/ThinLTO/X86/reduce-promotion.ll diff --git a/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll b/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll index a5792eee8abfb..14938cbaa465b 100644 --- a/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll +++ b/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll @@ -34,7 +34,7 @@ ; Round trip it through llvm-as ; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS ; CHECK-DIS: ^0 = module: (path: "{{.*}}cfi-devirt.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}})) -; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0)))))) +; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0)))))) ; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi"))))) ; guid = 7004155349499253778 ; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \ diff --git a/clang/test/CodeGen/distributed-thin-lto/cfi.ll b/clang/test/CodeGen/distributed-thin-lto/cfi.ll index 696f2dc4ea634..585602d43c79d 100644 --- a/clang/test/CodeGen/distributed-thin-lto/cfi.ll +++ b/clang/test/CodeGen/distributed-thin-lto/cfi.ll @@ -24,7 +24,7 @@ ; Round trip it through llvm-as ; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS ; CHECK-DIS: ^0 = module: (path: "{{.*}}cfi.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}})) -; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2))))) +; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2))))) ; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 7004155349499253778 ; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \ diff --git a/clang/test/CodeGen/thinlto-funcattr-prop.ll b/clang/test/CodeGen/thinlto-funcattr-prop.ll index daaa6e2da8048..e5f39ddd58a4f 100644 --- a/clang/test/CodeGen/thinlto-funcattr-prop.ll +++ b/clang/test/CodeGen/thinlto-funcattr-prop.ll @@ -15,9 +15,9 @@ ; RUN: llvm-dis %t1.o.1.1.promote.bc -o - | FileCheck %s --check-prefix=CHECK-IR ;; Summary for call_extern. Note that llvm-lto2 writes out the index before propagation occurs so call_extern doesn't have its flags updated. -; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^3))))) +; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^3))))) ;; Summary for extern -; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) ;--- a.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/lld/test/ELF/lto/comdat-nodeduplicate.ll b/lld/test/ELF/lto/comdat-nodeduplicate.ll index 928da5c82e518..96a78aa175e41 100644 --- a/lld/test/ELF/lto/comdat-nodeduplicate.ll +++ b/lld/test/ELF/lto/comdat-nodeduplicate.ll @@ -62,15 +62,15 @@ ; IR_AB-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]] ;; Check extra attributes. b.bc:__profc_foo is prevailing, so it can be internalized. -; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), -; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), +; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) ; IR_ABC-DAG: gv: (name: "__profd_foo", {{.*}} guid = [[PROFD:[0-9]+]] ; IR_ABC-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]] ;; b.bc:__profc_foo prevails c.bc:__profc_foo, so it is exported and therefore not internalized. -; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), -; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), +; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) ;--- a.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 5d5d70f89bde5..6c92c82188f1a 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -404,6 +404,7 @@ enum Kind { kw_importType, kw_definition, kw_declaration, + kw_noRenameOnPromotion, kw_function, kw_insts, kw_funcFlags, diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 5ede26cc7923c..b0b5ef9908a5e 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -269,6 +269,8 @@ struct ValueInfo { /// Checks if all copies are eligible for auto-hiding (have flag set). LLVM_ABI bool canAutoHide() const; + + LLVM_ABI bool noRenameOnPromotion() const; }; inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) { @@ -513,15 +515,21 @@ class GlobalValueSummary { /// transition unsigned Promoted : 1; + /// This field is written by the ThinLTO prelink stage to decide whether + /// a particular static global value should be promoted or not. + unsigned NoRenameOnPromotion : 1; + /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, GlobalValue::VisibilityTypes Visibility, bool NotEligibleToImport, bool Live, bool IsLocal, - bool CanAutoHide, ImportKind ImportType) + bool CanAutoHide, ImportKind ImportType, + bool NoRenameOnPromotion) : Linkage(Linkage), Visibility(Visibility), NotEligibleToImport(NotEligibleToImport), Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide), - ImportType(static_cast(ImportType)), Promoted(false) {} + ImportType(static_cast(ImportType)), Promoted(false), + NoRenameOnPromotion(NoRenameOnPromotion) {} }; private: @@ -631,6 +639,12 @@ class GlobalValueSummary { void setImportKind(ImportKind IK) { Flags.ImportType = IK; } + void setNoRenameOnPromotion(bool NoRenameOnPromotion) { + Flags.NoRenameOnPromotion = NoRenameOnPromotion; + } + + bool noRenameOnPromotion() const { return Flags.NoRenameOnPromotion; } + GlobalValueSummary::ImportKind importType() const { return static_cast(Flags.ImportType); } @@ -899,7 +913,8 @@ class FunctionSummary : public GlobalValueSummary { GlobalValue::LinkageTypes::AvailableExternallyLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false, - /*CanAutoHide=*/false, GlobalValueSummary::ImportKind::Definition), + /*CanAutoHide=*/false, GlobalValueSummary::ImportKind::Definition, + /*NoRenameOnPromotion=*/false), /*NumInsts=*/0, FunctionSummary::FFlags{}, SmallVector(), std::move(Edges), std::vector(), std::vector(), diff --git a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h index ccb77e75492af..546dbb6b64e20 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -140,7 +140,7 @@ template <> struct MappingTraits { struct GlobalValueSummaryYaml { // Commonly used fields unsigned Linkage, Visibility; - bool NotEligibleToImport, Live, IsLocal, CanAutoHide; + bool NotEligibleToImport, Live, IsLocal, CanAutoHide, NoRenameOnPromotion; unsigned ImportType; // Fields for AliasSummary std::optional Aliasee; @@ -191,6 +191,7 @@ template <> struct MappingTraits { io.mapOptional("Local", summary.IsLocal); io.mapOptional("CanAutoHide", summary.CanAutoHide); io.mapOptional("ImportType", summary.ImportType); + io.mapOptional("NoRenameOnPromotion", summary.NoRenameOnPromotion); io.mapOptional("Aliasee", summary.Aliasee); io.mapOptional("Refs", summary.Refs); io.mapOptional("TypeTests", summary.TypeTests); @@ -228,7 +229,8 @@ template <> struct CustomMappingTraits { static_cast(GVSum.Visibility), GVSum.NotEligibleToImport, GVSum.Live, GVSum.IsLocal, GVSum.CanAutoHide, - static_cast(GVSum.ImportType)); + static_cast(GVSum.ImportType), + GVSum.NoRenameOnPromotion); if (GVSum.Aliasee) { auto ASum = std::make_unique(GVFlags); V.try_emplace(*GVSum.Aliasee, /*IsAnalysis=*/false); @@ -272,9 +274,10 @@ template <> struct CustomMappingTraits { static_cast(FSum->flags().Live), static_cast(FSum->flags().DSOLocal), static_cast(FSum->flags().CanAutoHide), - FSum->flags().ImportType, /*Aliasee=*/std::nullopt, Refs, - FSum->type_tests(), FSum->type_test_assume_vcalls(), - FSum->type_checked_load_vcalls(), + FSum->flags().ImportType, + static_cast(FSum->flags().NoRenameOnPromotion), + /*Aliasee=*/std::nullopt, Refs, FSum->type_tests(), + FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), FSum->type_checked_load_const_vcalls()}); } else if (auto *ASum = dyn_cast(Sum.get()); @@ -286,6 +289,7 @@ template <> struct CustomMappingTraits { static_cast(ASum->flags().DSOLocal), static_cast(ASum->flags().CanAutoHide), ASum->flags().ImportType, + static_cast(ASum->flags().NoRenameOnPromotion), /*Aliasee=*/ASum->getAliaseeGUID()}); } } diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 3e877d22c3f6c..38349b604b6b3 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -65,7 +65,8 @@ LLVM_ABI void thinLTOInternalizeAndPromoteInIndex( ModuleSummaryIndex &Index, function_ref isExported, function_ref - isPrevailing); + isPrevailing, + DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); /// Computes a unique hash for the Module considering the current list of /// export/import and other global analysis results. diff --git a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h index 2e33a4098be1b..ba0b22b799ebe 100644 --- a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -271,14 +271,16 @@ LLVM_ABI void getVisibleToRegularObjVtableGUIDs( /// devirtualized target name will need adjustment). LLVM_ABI void runWholeProgramDevirtOnIndex( ModuleSummaryIndex &Summary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap); + std::map> &LocalWPDTargetsMap, + DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); /// Call after cross-module importing to update the recorded single impl /// devirt target names for any locals that were exported. LLVM_ABI void updateIndexWPDForExports( ModuleSummaryIndex &Summary, function_ref isExported, - std::map> &LocalWPDTargetsMap); + std::map> &LocalWPDTargetsMap, + DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); } // end namespace llvm diff --git a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h index c4c7b403bed86..e22bea53a18a6 100644 --- a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -63,7 +63,8 @@ class FunctionImportGlobalProcessing { DenseMap RenamedComdats; /// Check if we should promote the given local value to global scope. - bool shouldPromoteLocalToGlobal(const GlobalValue *SGV, ValueInfo VI); + bool shouldPromoteLocalToGlobal(const GlobalValue *SGV, + GlobalValueSummary *Summary); #ifndef NDEBUG /// Check if the given value is a local that can't be renamed (promoted). diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 069f4ae1790b1..f504519ebb5a6 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -712,7 +712,8 @@ static void computeFunctionSummary( GlobalValueSummary::GVFlags Flags( F.getLinkage(), F.getVisibility(), NotEligibleForImport, /* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(), - GlobalValueSummary::ImportKind::Definition); + GlobalValueSummary::ImportKind::Definition, + /* NoRenameOnPromotion = */ false); FunctionSummary::FFlags FunFlags{ F.doesNotAccessMemory(), F.onlyReadsMemory() && !F.doesNotAccessMemory(), F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(), @@ -870,7 +871,7 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, GlobalValueSummary::GVFlags Flags( V.getLinkage(), V.getVisibility(), NonRenamableLocal, /* Live = */ false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, /* NoRenameOnPromotion = */ false); VTableFuncList VTableFuncs; // If splitting is not enabled, then we compute the summary information @@ -917,7 +918,7 @@ static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, GlobalValueSummary::GVFlags Flags( A.getLinkage(), A.getVisibility(), NonRenamableLocal, /* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, /* NoRenameOnPromotion = */ false); auto AS = std::make_unique(Flags); auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID()); assert(AliaseeVI && "Alias expects aliasee summary to be available"); @@ -999,7 +1000,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( /* NotEligibleToImport = */ true, /* Live = */ true, /* Local */ GV->isDSOLocal(), GV->canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, + /* NoRenameOnPromotion = */ false); CantBePromoted.insert(GV->getGUID()); // Create the appropriate summary type. if (Function *F = dyn_cast(GV)) { diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 8d20ff72a8505..4840d04f6b78d 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -809,6 +809,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(importType); KEYWORD(definition); KEYWORD(declaration); + KEYWORD(noRenameOnPromotion); KEYWORD(function); KEYWORD(insts); KEYWORD(funcFlags); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 09b030b28dce8..551b88d8b435b 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -10023,7 +10023,7 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); unsigned InstCount; SmallVector Calls; FunctionSummary::TypeIdInfo TypeIdInfo; @@ -10111,7 +10111,7 @@ bool LLParser::parseVariableSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false, /* WriteOnly */ false, /* Constant */ false, @@ -10170,7 +10170,7 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition); + GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseModuleReference(ModulePath) || @@ -10967,6 +10967,12 @@ bool LLParser::parseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { GVFlags.ImportType = static_cast(IK); Lex.Lex(); break; + case lltok::kw_noRenameOnPromotion: + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) + return true; + GVFlags.NoRenameOnPromotion = Flag; + break; default: return error(Lex.getLoc(), "expected gv flag type"); } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index c0807c7be3e4f..a781a43112f8c 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1175,6 +1175,7 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags, auto Linkage = GlobalValue::LinkageTypes(RawFlags & 0xF); // 4 bits auto Visibility = GlobalValue::VisibilityTypes((RawFlags >> 8) & 3); // 2 bits auto IK = GlobalValueSummary::ImportKind((RawFlags >> 10) & 1); // 1 bit + bool NoRenameOnPromotion = ((RawFlags >> 11) & 1); // 1 bit RawFlags = RawFlags >> 4; bool NotEligibleToImport = (RawFlags & 0x1) || Version < 3; // The Live flag wasn't introduced until version 3. For dead stripping @@ -1185,7 +1186,8 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags, bool AutoHide = (RawFlags & 0x8); return GlobalValueSummary::GVFlags(Linkage, Visibility, NotEligibleToImport, - Live, Local, AutoHide, IK); + Live, Local, AutoHide, IK, + NoRenameOnPromotion); } // Decode the flags for GlobalVariable in the summary diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index cc0491bd8577f..f0316116d0107 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1337,6 +1337,8 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags, unsigned ImportType = Flags.ImportType | ImportAsDecl; RawFlags |= (ImportType << 10); // 1 bit + RawFlags |= (Flags.NoRenameOnPromotion << 11); // 1 bit + return RawFlags; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 35a19091aa097..dd99b14d45d6e 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -3730,6 +3730,7 @@ void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) { Out << ", canAutoHide: " << GVFlags.CanAutoHide; Out << ", importType: " << getImportTypeName(GlobalValueSummary::ImportKind(GVFlags.ImportType)); + Out << ", noRenameOnPromotion: " << GVFlags.NoRenameOnPromotion; Out << ")"; if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind) diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp index 9a3bb970494a2..98876c87ef6db 100644 --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -686,6 +686,8 @@ void ModuleSummaryIndex::exportToDot( A.addComment("definition"); else if (Flags.ImportType == GlobalValueSummary::ImportKind::Declaration) A.addComment("declaration"); + if (Flags.NoRenameOnPromotion) + A.addComment("noRenameOnPromotion"); if (GUIDPreservedSymbols.count(SummaryIt.first)) A.addComment("preserved"); diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 853f6427f9c8c..bf2d2e6b9da9d 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -110,6 +110,7 @@ static cl::opt namespace llvm { extern cl::opt CodeGenDataThinLTOTwoRounds; extern cl::opt ForceImportAll; +extern cl::opt AlwaysRenamePromotedLocals; } // end namespace llvm namespace llvm { @@ -509,7 +510,8 @@ void llvm::thinLTOResolvePrevailingInIndex( static void thinLTOInternalizeAndPromoteGUID( ValueInfo VI, function_ref isExported, function_ref - isPrevailing) { + isPrevailing, + DenseSet *ExternallyVisibleSymbolNamesPtr) { // Before performing index-based internalization and promotion for this GUID, // the local flag should be consistent with the summary list linkage types. VI.verifyLocal(); @@ -518,12 +520,24 @@ static void thinLTOInternalizeAndPromoteGUID( VI.getSummaryList().size() == 1 && !GlobalValue::isLocalLinkage(VI.getSummaryList().front()->linkage()); + bool NameRecorded = false; for (auto &S : VI.getSummaryList()) { // First see if we need to promote an internal value because it is not // exported. if (isExported(S->modulePath(), VI)) { - if (GlobalValue::isLocalLinkage(S->linkage())) + if (GlobalValue::isLocalLinkage(S->linkage())) { + // Only the first local GlobalValue in a list of summaries does not + // need renaming. In rare cases if there exist more than one summaries + // in the list, the rest of them must have renaming (through promotion) + // to avoid conflict. + if (ExternallyVisibleSymbolNamesPtr && !NameRecorded) { + NameRecorded = true; + if (ExternallyVisibleSymbolNamesPtr->insert(VI.name()).second) + S->setNoRenameOnPromotion(true); + } + S->promote(); + } continue; } @@ -593,11 +607,14 @@ void llvm::thinLTOInternalizeAndPromoteInIndex( ModuleSummaryIndex &Index, function_ref isExported, function_ref - isPrevailing) { + isPrevailing, + DenseSet *ExternallyVisibleSymbolNamesPtr) { assert(!Index.withInternalizeAndPromote()); + for (auto &I : Index) thinLTOInternalizeAndPromoteGUID(Index.getValueInfo(I), isExported, - isPrevailing); + isPrevailing, + ExternallyVisibleSymbolNamesPtr); Index.setWithInternalizeAndPromote(); } @@ -2047,8 +2064,19 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, // no index entries in the typeIdMetadata map (e.g. if we are instead // performing IR-based WPD in hybrid regular/thin LTO mode). std::map> LocalWPDTargetsMap; + DenseSet ExternallyVisibleSymbolNames; + + // Used by the promotion-time renaming logic. When non-null, this set + // identifies symbols that should not be renamed during promotion. + // It is non-null only when whole-program visibility is enabled and + // renaming is not forced. Otherwise, the default renaming behavior applies. + DenseSet *ExternallyVisibleSymbolNamesPtr = + (WholeProgramVisibilityEnabledInLTO && !AlwaysRenamePromotedLocals) + ? &ExternallyVisibleSymbolNames + : nullptr; runWholeProgramDevirtOnIndex(ThinLTO.CombinedIndex, ExportedGUIDs, - LocalWPDTargetsMap); + LocalWPDTargetsMap, + ExternallyVisibleSymbolNamesPtr); auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { return ThinLTO.isPrevailingModuleForGUID(GUID, S->modulePath()); @@ -2108,10 +2136,27 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, // Update local devirtualized targets that were exported by cross-module // importing or by other devirtualizations marked in the ExportedGUIDs set. updateIndexWPDForExports(ThinLTO.CombinedIndex, isExported, - LocalWPDTargetsMap); + LocalWPDTargetsMap, ExternallyVisibleSymbolNamesPtr); + + if (ExternallyVisibleSymbolNamesPtr) { + // Add to ExternallyVisibleSymbolNames the set of unique names used by all + // externally visible symbols in the index. + for (auto &I : ThinLTO.CombinedIndex) { + ValueInfo VI = ThinLTO.CombinedIndex.getValueInfo(I); + for (const auto &Summary : VI.getSummaryList()) { + const GlobalValueSummary *Base = Summary->getBaseObject(); + if (GlobalValue::isLocalLinkage(Base->linkage())) + continue; + + ExternallyVisibleSymbolNamesPtr->insert(VI.name()); + break; + } + } + } thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported, - isPrevailing); + isPrevailing, + ExternallyVisibleSymbolNamesPtr); auto recordNewLinkage = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID, diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 8c2420a45a24c..e057761256775 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -773,6 +773,11 @@ struct DevirtIndex { // resolution for local targets in case they are exported by cross module // importing. std::map> &LocalWPDTargetsMap; + // We have hardcoded the promoted and renamed function name in the WPD + // summary, so we need to ensure that they will be renamed. Note this and + // that adding the current names to this set ensures we continue to rename + // them. + DenseSet *ExternallyVisibleSymbolNamesPtr; MapVector CallSlots; @@ -781,9 +786,11 @@ struct DevirtIndex { DevirtIndex( ModuleSummaryIndex &ExportSummary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap) + std::map> &LocalWPDTargetsMap, + DenseSet *ExternallyVisibleSymbolNamesPtr) : ExportSummary(ExportSummary), ExportedGUIDs(ExportedGUIDs), - LocalWPDTargetsMap(LocalWPDTargetsMap) { + LocalWPDTargetsMap(LocalWPDTargetsMap), + ExternallyVisibleSymbolNamesPtr(ExternallyVisibleSymbolNamesPtr) { FunctionsToSkip.init(SkipFunctionNames); } @@ -973,14 +980,18 @@ void llvm::updateVCallVisibilityInIndex( void llvm::runWholeProgramDevirtOnIndex( ModuleSummaryIndex &Summary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap) { - DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap).run(); + std::map> &LocalWPDTargetsMap, + DenseSet *ExternallyVisibleSymbolNamesPtr) { + DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap, + ExternallyVisibleSymbolNamesPtr) + .run(); } void llvm::updateIndexWPDForExports( ModuleSummaryIndex &Summary, function_ref IsExported, - std::map> &LocalWPDTargetsMap) { + std::map> &LocalWPDTargetsMap, + DenseSet *ExternallyVisibleSymbolNamesPtr) { for (auto &T : LocalWPDTargetsMap) { auto &VI = T.first; // This was enforced earlier during trySingleImplDevirt. @@ -996,6 +1007,8 @@ void llvm::updateIndexWPDForExports( assert(TIdSum); auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset); assert(WPDRes != TIdSum->WPDRes.end()); + if (ExternallyVisibleSymbolNamesPtr) + ExternallyVisibleSymbolNamesPtr->insert(WPDRes->second.SingleImplName); WPDRes->second.SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal( WPDRes->second.SingleImplName, Summary.getModuleHash(S->modulePath())); @@ -1429,13 +1442,15 @@ bool DevirtIndex::trySingleImplDevirt(MutableArrayRef TargetsForSlot, // step. Res->TheKind = WholeProgramDevirtResolution::SingleImpl; if (GlobalValue::isLocalLinkage(S->linkage())) { - if (IsExported) + if (IsExported) { // If target is a local function and we are exporting it by // devirtualizing a call in another module, we need to record the // promoted name. + if (ExternallyVisibleSymbolNamesPtr) + ExternallyVisibleSymbolNamesPtr->insert(TheFn.name()); Res->SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal( TheFn.name(), ExportSummary.getModuleHash(S->modulePath())); - else { + } else { LocalWPDTargetsMap[TheFn].push_back(SlotSummary); Res->SingleImplName = std::string(TheFn.name()); } diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp index d31154fcf085d..475699c42b21e 100644 --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -28,6 +28,14 @@ static cl::opt UseSourceFilenameForPromotedLocals( "This requires that the source filename has a unique name / " "path to avoid name collisions.")); +/// FIXME: The current optimization that avoids unnecessary renaming of +/// promoted locals is incompatible with distributed ThinLTO and therefore +/// must be enabled by default. +cl::opt + AlwaysRenamePromotedLocals("always-rename-promoted-locals", cl::init(true), + cl::Hidden, + cl::desc("Always rename promoted locals.")); + cl::list MoveSymbolGUID( "thinlto-move-symbols", cl::desc( @@ -81,7 +89,7 @@ bool FunctionImportGlobalProcessing::doImportAsDefinition( } bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal( - const GlobalValue *SGV, ValueInfo VI) { + const GlobalValue *SGV, GlobalValueSummary *Summary) { assert(SGV->hasLocalLinkage()); // Ifuncs and ifunc alias does not have summary. @@ -112,8 +120,6 @@ bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal( // same-named source files that were compiled in their respective directories // (so the source file name and resulting GUID is the same). Find the one // in this module. - auto Summary = ImportIndex.findSummaryInModule( - VI, SGV->getParent()->getModuleIdentifier()); assert(Summary && "Missing summary for global value when exporting"); auto Linkage = Summary->linkage(); if (!GlobalValue::isLocalLinkage(Linkage)) { @@ -306,10 +312,18 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { } } - if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, VI)) { + GlobalValueSummary *Summary = nullptr; + if (VI && GV.hasLocalLinkage()) + Summary = ImportIndex.findSummaryInModule( + VI, GV.getParent()->getModuleIdentifier()); + + if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, Summary)) { // Save the original name string before we rename GV below. auto Name = GV.getName().str(); - GV.setName(getPromotedName(&GV)); + if (AlwaysRenamePromotedLocals || !Summary || + !Summary->noRenameOnPromotion()) + GV.setName(getPromotedName(&GV)); + GV.setLinkage(getLinkage(&GV, /* DoPromote */ true)); assert(!GV.hasLocalLinkage()); GV.setVisibility(GlobalValue::HiddenVisibility); diff --git a/llvm/test/Assembler/thinlto-memprof-summary.ll b/llvm/test/Assembler/thinlto-memprof-summary.ll index 4e4a928c1f024..225fda60f8550 100644 --- a/llvm/test/Assembler/thinlto-memprof-summary.ll +++ b/llvm/test/Assembler/thinlto-memprof-summary.ll @@ -12,22 +12,22 @@ ^0 = module: (path: "thinlto-memprof-summary.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ;; Function with single alloc, multiple memprof MIBs, no versioning -^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) +^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) ;; Function with callsite stack ids calling above function, no versioning -^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) +^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) ;; Function with multiple allocs, multiple memprof MIBs, multiple versions -^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) +^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) ;; Function with callsite stack ids calling above function, multiple versions -^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) +^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) ;; Function with null callsite stack id (can happen in distributed indexes if callsite not imported) -^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) +^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) ; Make sure we get back from llvm-dis what we put in via llvm-as. ; CHECK: ^0 = module: (path: "thinlto-memprof-summary.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) -; CONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) -; NOCONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()), (type: hot, stackIds: ()))))))) -; CHECK: ^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) -; CONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) -; NOCONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: ()), (type: notcold, stackIds: ()))))))) -; CHECK: ^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) -; CHECK: ^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) +; CONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) +; NOCONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()), (type: hot, stackIds: ()))))))) +; CHECK: ^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) +; CONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) +; NOCONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: ()), (type: notcold, stackIds: ()))))))) +; CHECK: ^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) +; CHECK: ^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) diff --git a/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll b/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll index 117280a279d09..83e0c8cbc8a13 100644 --- a/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll +++ b/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll @@ -8,5 +8,5 @@ source_filename = "index.bc" ; CHECK: ^0 = module: (path: "[Regular LTO]", hash: (0, 0, 0, 0, 0)) ^1 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952)) ; CHECK-NEXT: ^1 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952)) -^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1), function: (module: ^1, flags: (linkage: available_externally, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK-NEXT: ^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1), function: (module: ^1, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) +^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1), function: (module: ^1, flags: (linkage: available_externally, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK-NEXT: ^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1), function: (module: ^1, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) diff --git a/llvm/test/Assembler/thinlto-summary-visibility.ll b/llvm/test/Assembler/thinlto-summary-visibility.ll index 67ddcb961d7ae..08f7d06433505 100644 --- a/llvm/test/Assembler/thinlto-summary-visibility.ll +++ b/llvm/test/Assembler/thinlto-summary-visibility.ll @@ -4,9 +4,9 @@ ^0 = module: (path: "thinlto-summary-visibility1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ^1 = module: (path: "thinlto-summary-visibility2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156)) -; CHECK: ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) -; CHECK-NEXT: ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) -; CHECK-NEXT: ^4 = gv: (guid: 4, summaries: (function: (module: ^0, flags: (linkage: external, visibility: hidden, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) +; CHECK: ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) +; CHECK-NEXT: ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) +; CHECK-NEXT: ^4 = gv: (guid: 4, summaries: (function: (module: ^0, flags: (linkage: external, visibility: hidden, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default), insts: 10))) ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected), insts: 10))) diff --git a/llvm/test/Assembler/thinlto-summary.ll b/llvm/test/Assembler/thinlto-summary.ll index 21da14850b962..5b907f9a06039 100644 --- a/llvm/test/Assembler/thinlto-summary.ll +++ b/llvm/test/Assembler/thinlto-summary.ll @@ -17,13 +17,13 @@ ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, relbf: 256, tail: 1))))) ; Summaries with different linkage types. -^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1))) +^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) ; Make this one an alias with a forward reference to aliasee. -^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), aliasee: ^14))) +^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) -^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition), insts: 1))) +^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0)))) ; Test appending globel variable with reference (tests backward reference on @@ -54,14 +54,14 @@ ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) ; Function summary with an import type of declaration -^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, importType: declaration), insts: 5))) +^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, importType: declaration, noRenameOnPromotion: 0), insts: 5))) ; Alias summary with null aliasee. ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: null))) ; GUID that are 64-bit -^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1))) +^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) ; Test TypeId summaries: @@ -80,33 +80,33 @@ ; Make sure we get back from llvm-dis essentially what we put in via llvm-as. ; CHECK: ^0 = module: (path: "thinlto-summary1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ; CHECK: ^1 = module: (path: "thinlto-summary2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156)) -; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none, tail: 1)), refs: (^11, readonly ^13, writeonly ^14)))) +; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none, tail: 1)), refs: (^11, readonly ^13, writeonly ^14)))) ;; relbf is not emitted since this is a combined summary, and that is only ;; emitted for per-module summaries. Additionally, it is now deprecated. -; CHECK: ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10, calls: ((callee: ^15, tail: 1))))) -; CHECK: ^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK: ^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: ^14))) -; CHECK: ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK: ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition), insts: 1))) -; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) -; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^4)))) -; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 0, constant: 0)))) -; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) -; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) -; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 1, hasUnknownCall: 1, mustBeUnreachable: 0)))) -; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 1), calls: ((callee: ^15))))) -; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: ^14))) -; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (^27, ^29))))) -; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^30, offset: 16)))))) -; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^28, offset: 16)))))) -; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^30, offset: 16), args: (42)), (vFuncId: (^30, offset: 24))))))) -; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) -; CHECK: ^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: declaration), insts: 5))) -; CHECK: ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: null))) -; CHECK: ^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10, calls: ((callee: ^15, tail: 1))))) +; CHECK: ^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) +; CHECK: ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^4)))) +; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 0, constant: 0)))) +; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 1, hasUnknownCall: 1, mustBeUnreachable: 0)))) +; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 1), calls: ((callee: ^15))))) +; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) +; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (^27, ^29))))) +; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^30, offset: 16)))))) +; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^28, offset: 16)))))) +; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^30, offset: 16), args: (42)), (vFuncId: (^30, offset: 24))))))) +; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) +; CHECK: ^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: declaration, noRenameOnPromotion: 0), insts: 5))) +; CHECK: ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: null))) +; CHECK: ^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) ; CHECK: ^27 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584 ; CHECK: ^28 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976 ; CHECK: ^29 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778 diff --git a/llvm/test/Assembler/thinlto-vtable-summary.ll b/llvm/test/Assembler/thinlto-vtable-summary.ll index 80720287f7a09..7b8e4f2a928a4 100644 --- a/llvm/test/Assembler/thinlto-vtable-summary.ll +++ b/llvm/test/Assembler/thinlto-vtable-summary.ll @@ -29,9 +29,9 @@ declare i32 @_ZN1C1fEi(ptr, i32) ^0 = module: (path: "", hash: (0, 0, 0, 0, 0)) ^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257 -^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367 +^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367 ^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394 -^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296 +^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296 ^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556 ^6 = typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778 ^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976 diff --git a/llvm/test/Bitcode/thinlto-alias.ll b/llvm/test/Bitcode/thinlto-alias.ll index 7deb2d8259e32..4191983055b2c 100644 --- a/llvm/test/Bitcode/thinlto-alias.ll +++ b/llvm/test/Bitcode/thinlto-alias.ll @@ -53,11 +53,11 @@ entry: declare void @analias(...) ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) -; DIS: ^1 = gv: (name: "analias", summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), aliasee: ^2))) ; guid = 12695095382722328222 -; DIS: ^2 = gv: (name: "aliasee", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) ; guid = 17407585008595848568 +; DIS: ^1 = gv: (name: "analias", summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^2))) ; guid = 12695095382722328222 +; DIS: ^2 = gv: (name: "aliasee", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) ; guid = 17407585008595848568 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-alias.ll.tmp.o", hash: (0, 0, 0, 0, 0)) ; COMBINED-DIS: ^1 = module: (path: "{{.*}}thinlto-alias.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^2 = gv: (guid: 12695095382722328222, summaries: (alias: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), aliasee: ^4))) -; COMBINED-DIS: ^3 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^2))))) -; COMBINED-DIS: ^4 = gv: (guid: 17407585008595848568, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^2 = gv: (guid: 12695095382722328222, summaries: (alias: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^4))) +; COMBINED-DIS: ^3 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^2))))) +; COMBINED-DIS: ^4 = gv: (guid: 17407585008595848568, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll index 576261e5392b2..33288be2d2195 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll @@ -150,16 +150,16 @@ declare void @none3() #1 ; DIS: ^6 = gv: (name: "cold") ; guid = 11668175513417606517 ; DIS: ^7 = gv: (name: "hot4") ; guid = 13161834114071272798 ; DIS: ^8 = gv: (name: "none3") ; guid = 16213681105727317812 -; DIS: ^9 = gv: (name: "hot_function", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^7, hotness: cold), (callee: ^10, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^8, hotness: none), (callee: ^1, hotness: critical))))) ; guid = 17381606045411660303 +; DIS: ^9 = gv: (name: "hot_function", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^7, hotness: cold), (callee: ^10, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^8, hotness: none), (callee: ^1, hotness: critical))))) ; guid = 17381606045411660303 ; DIS: ^10 = gv: (name: "none1") ; guid = 17712061229457633252 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-function-summary-callgraph-profile-summary.ll.tmp.o", hash: (0, 0, 0, 0, 0)) ; COMBINED-DIS: ^1 = module: (path: "{{.*}}thinlto-function-summary-callgraph-profile-summary.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^2 = gv: (guid: 3741006263754194003, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^3 = gv: (guid: 5026609803865204483, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^4 = gv: (guid: 8117347573235780485, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^5 = gv: (guid: 9453975128311291976, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^6 = gv: (guid: 11668175513417606517, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^7 = gv: (guid: 16213681105727317812, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) -; COMBINED-DIS: ^8 = gv: (guid: 17381606045411660303, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^9, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^7, hotness: none))))) -; COMBINED-DIS: ^9 = gv: (guid: 17712061229457633252, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^2 = gv: (guid: 3741006263754194003, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^3 = gv: (guid: 5026609803865204483, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^4 = gv: (guid: 8117347573235780485, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^5 = gv: (guid: 9453975128311291976, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^6 = gv: (guid: 11668175513417606517, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^7 = gv: (guid: 16213681105727317812, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^8 = gv: (guid: 17381606045411660303, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^9, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^7, hotness: none))))) +; COMBINED-DIS: ^9 = gv: (guid: 17712061229457633252, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll index 22e27c45324af..d50bad6cbc128 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll @@ -39,5 +39,5 @@ declare void @func(...) #1 ; DIS: ^1 = gv: (name: "func") ; guid = 7289175272376759421 ;; We should have ignored the relbf in the old bitcode, and it no longer shows ;; up in the summary. -; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 3, calls: ((callee: ^1)), refs: (readonly ^3)))) ; guid = 15822663052811949562 +; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 3, calls: ((callee: ^1)), refs: (readonly ^3)))) ; guid = 15822663052811949562 ; DIS: ^3 = gv: (name: "undefinedglob") ; guid = 18036901804029949403 diff --git a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll index c76d70b8c4cc0..a25901a572d30 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll @@ -148,18 +148,18 @@ entry: ; order, which depends on GUID, and the private function Y GUID will depend ; on the path to the test. ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) -; DIS-DAG: = gv: (name: "Z", summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = 104084381700047393 -; DIS-DAG: = gv: (name: "X", summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 1881667236089500162 -; DIS-DAG: = gv: (name: "W", summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}}, tail: 1)), refs: (^{{.*}})))) ; guid = 5790125716599269729 +; DIS-DAG: = gv: (name: "Z", summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = 104084381700047393 +; DIS-DAG: = gv: (name: "X", summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 1881667236089500162 +; DIS-DAG: = gv: (name: "W", summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}}, tail: 1)), refs: (^{{.*}})))) ; guid = 5790125716599269729 ; DIS-DAG: = gv: (name: "foo") ; guid = 6699318081062747564 ; DIS-DAG: = gv: (name: "func") ; guid = 7289175272376759421 ; DIS-DAG: = gv: (name: "func3") ; guid = 11517462787082255043 ; Check that default value of writeonly attribute is zero for constant variables -; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 0, constant: 1)))) ; guid = 12887606300320728018 +; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 0, constant: 1)))) ; guid = 12887606300320728018 ; DIS-DAG: = gv: (name: "func2") ; guid = 14069196320850861797 ; DIS-DAG: = gv: (name: "llvm.ctpop.i8") ; guid = 15254915475081819833 -; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 9, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562 -; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 1, constant: 0), refs: (^{{.*}})))) ; guid = 16434608426314478903 +; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 9, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562 +; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0), refs: (^{{.*}})))) ; guid = 16434608426314478903 ; Don't try to match the exact GUID. Since it is private, the file path ; will get hashed, and that will be test dependent. -; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 14, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = +; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 14, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = diff --git a/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll index 3f71a3dfe0591..74980ad76304c 100644 --- a/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll +++ b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll @@ -18,7 +18,7 @@ ; RUN: llvm-dis --print-thinlto-index-only %t.o -o - | FileCheck %s --check-prefix=DIS ; DIS: ^0 = module: (path: "{{.*}}thinlto-index-disassembled-by-llvm-dis.ll.tmp -; DIS: ^1 = gv: (name: "aplusb", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2))) ; guid = +; DIS: ^1 = gv: (name: "aplusb", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2))) ; guid = source_filename = "add.cpp" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/Bitcode/thinlto-type-tests.ll b/llvm/test/Bitcode/thinlto-type-tests.ll index 6dc49b849c2fe..6d329d5bce949 100644 --- a/llvm/test/Bitcode/thinlto-type-tests.ll +++ b/llvm/test/Bitcode/thinlto-type-tests.ll @@ -37,11 +37,11 @@ declare i1 @llvm.type.test(i8*, metadata) nounwind readnone ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) ; DIS: ^1 = gv: (name: "llvm.type.test") ; guid = 608142985856744218 -; DIS: ^2 = gv: (name: "h", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) ; guid = 8124147457056772133 -; DIS: ^3 = gv: (name: "g", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) ; guid = 13146401226427987378 -; DIS: ^4 = gv: (name: "f", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) ; guid = 14740650423002898831 +; DIS: ^2 = gv: (name: "h", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) ; guid = 8124147457056772133 +; DIS: ^3 = gv: (name: "g", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) ; guid = 13146401226427987378 +; DIS: ^4 = gv: (name: "f", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) ; guid = 14740650423002898831 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-type-tests.ll.tmp.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^1 = gv: (guid: 8124147457056772133, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) -; COMBINED-DIS: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) -; COMBINED-DIS: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) +; COMBINED-DIS: ^1 = gv: (guid: 8124147457056772133, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) +; COMBINED-DIS: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) +; COMBINED-DIS: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) diff --git a/llvm/test/Bitcode/thinlto-type-vcalls.ll b/llvm/test/Bitcode/thinlto-type-vcalls.ll index 16c93097101df..f10f6535c7f08 100644 --- a/llvm/test/Bitcode/thinlto-type-vcalls.ll +++ b/llvm/test/Bitcode/thinlto-type-vcalls.ll @@ -112,19 +112,19 @@ declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata) ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) ; DIS: ^1 = gv: (name: "llvm.type.test") ; guid = 608142985856744218 -; DIS: ^2 = gv: (name: "f1", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 2072045998141807037 -; DIS: ^3 = gv: (name: "f3", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 4197650231481825559 +; DIS: ^2 = gv: (name: "f1", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 2072045998141807037 +; DIS: ^3 = gv: (name: "f3", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 4197650231481825559 ; DIS: ^4 = gv: (name: "llvm.type.checked.load") ; guid = 5568222536364573403 ; DIS: ^5 = gv: (name: "llvm.assume") ; guid = 6385187066495850096 -; DIS: ^6 = gv: (name: "f2", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) ; guid = 8471399308421654326 -; DIS: ^7 = gv: (name: "f4", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) ; guid = 10064745020953272174 -; DIS: ^8 = gv: (name: "f5", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) ; guid = 11686717102184386164 -; DIS: ^9 = gv: (name: "f6", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) ; guid = 11834966808443348068 +; DIS: ^6 = gv: (name: "f2", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) ; guid = 8471399308421654326 +; DIS: ^7 = gv: (name: "f4", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) ; guid = 10064745020953272174 +; DIS: ^8 = gv: (name: "f5", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) ; guid = 11686717102184386164 +; DIS: ^9 = gv: (name: "f6", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) ; guid = 11834966808443348068 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-type-vcalls.ll.tmp.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^1 = gv: (guid: 2072045998141807037, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) -; COMBINED-DIS: ^2 = gv: (guid: 4197650231481825559, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) -; COMBINED-DIS: ^3 = gv: (guid: 8471399308421654326, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) -; COMBINED-DIS: ^4 = gv: (guid: 10064745020953272174, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) -; COMBINED-DIS: ^5 = gv: (guid: 11686717102184386164, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) -; COMBINED-DIS: ^6 = gv: (guid: 11834966808443348068, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) +; COMBINED-DIS: ^1 = gv: (guid: 2072045998141807037, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) +; COMBINED-DIS: ^2 = gv: (guid: 4197650231481825559, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) +; COMBINED-DIS: ^3 = gv: (guid: 8471399308421654326, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) +; COMBINED-DIS: ^4 = gv: (guid: 10064745020953272174, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) +; COMBINED-DIS: ^5 = gv: (guid: 11686717102184386164, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) +; COMBINED-DIS: ^6 = gv: (guid: 11834966808443348068, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) diff --git a/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll b/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll new file mode 100644 index 0000000000000..5906da234b199 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll @@ -0,0 +1,20 @@ +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-pc-linux-gnu" + +source_filename = "foo.c" + +define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { + %2 = tail call fastcc i32 @foo(i32 noundef %0) + %3 = shl nsw i32 %0, 1 + %4 = tail call fastcc i32 @foo(i32 noundef %3) + %5 = add nsw i32 %4, %2 + ret i32 %5 +} + +define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { + %2 = add nsw i32 %0, 5 + %3 = sdiv i32 %2, %0 + ret i32 %3 +} + +attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll index abfe820075bb9..5475ca1bf1d44 100644 --- a/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll +++ b/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll @@ -48,9 +48,9 @@ define void @caller_nounwind() { ; CHECK-DAG: attributes [[ATTR_NOUNWIND]] = { norecurse nounwind } ; CHECK-DAG: attributes [[ATTR_MAYTHROW]] = { norecurse } -; SUMMARY-DAG: = gv: (name: "cleanupret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) -; SUMMARY-DAG: = gv: (name: "resume", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) -; SUMMARY-DAG: = gv: (name: "catchret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "cleanupret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "resume", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "catchret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ;--- callees.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll b/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll index 67acc2a2892db..431e2a9254887 100644 --- a/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll +++ b/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll @@ -23,4 +23,4 @@ entry: } attributes #0 = { alwaysinline nounwind uwtable } -; CHECK2: ^2 = gv: (guid: {{.*}}, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK2: ^2 = gv: (guid: {{.*}}, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll index 72550fa4d6f0b..c1b09c5b42fa9 100644 --- a/llvm/test/ThinLTO/X86/import_callee_declaration.ll +++ b/llvm/test/ThinLTO/X86/import_callee_declaration.ll @@ -67,12 +67,12 @@ ; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS ; ; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) -; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), insts: 8, {{.*}}))) ; When alias is imported as a copy of the aliasee, but the aliasee is not being ; imported by itself, the aliasee should be null. -; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null))) -; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) -; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: [[LARGEINDIRECT]]))) +; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), aliasee: null))) +; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), insts: 8, {{.*}}))) +; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), aliasee: [[LARGEINDIRECT]]))) ; RUN: opt -passes=function-import -import-all-index -summary-file=main.bc.thinlto.bc main.bc -o main-after-import.bc ; RUN: llvm-dis -o - main-after-import.bc | FileCheck %s --check-prefix=MAIN-IMPORT diff --git a/llvm/test/ThinLTO/X86/load-store-caching.ll b/llvm/test/ThinLTO/X86/load-store-caching.ll index b25308bf17616..85156881f0429 100644 --- a/llvm/test/ThinLTO/X86/load-store-caching.ll +++ b/llvm/test/ThinLTO/X86/load-store-caching.ll @@ -22,5 +22,5 @@ entry: } ; CHECK: ^0 = module: -; CHECK-NEXT: ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid = -; CHECK-NEXT: ^2 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 3, refs: (^1)))) ; guid = +; CHECK-NEXT: ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid = +; CHECK-NEXT: ^2 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 3, refs: (^1)))) ; guid = diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll b/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll new file mode 100644 index 0000000000000..f9d26e7829fd9 --- /dev/null +++ b/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll @@ -0,0 +1,99 @@ +; Test that renaming is still performed even when we try to avoid always renaming +; on promotion. The devirtualization promotes an internal virtual target to a +; uniqued hidden symbol from a static function, and later on the static funciton +; is promoted to the same hidden symbol. + +; Set up +; RUN: rm -rf %t +; RUN: mkdir -p %t +; RUN: split-file %s %t + +; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc +; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc + +; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ +; RUN: --whole-program-visibility-enabled-in-lto=true \ +; RUN: -always-rename-promoted-locals=false \ +; RUN: -save-temps -o %t/lto-out \ +; RUN: -r %t/a.bc,test,px \ +; RUN: -r %t/b.bc,_ZN1B1fEi,p \ +; RUN: -r %t/b.bc,test2,px \ +; RUN: -r %t/b.bc,_ZTV1B,px + +; RUN: llvm-nm %t/lto-out.1 | FileCheck %s --check-prefix=NM-INDEX1 +; RUN: llvm-nm %t/lto-out.2 | FileCheck %s --check-prefix=NM-INDEX2 + +; NM-INDEX1: U _ZN1A1nEi.llvm. +; NM-INDEX2-NOT: U _ZN1A1nEi +; NM-INDEX2: T _ZN1A1nEi.llvm. +; NM-INDEX2-NOT: U _ZN1A1nEi + +; RUN: llvm-dis %t/lto-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT-INDEX1 +; RUN: llvm-dis %t/lto-out.2.4.opt.bc -o - | FileCheck %s --check-prefix=OPT-INDEX2 + +; OPT-INDEX1: %call = tail call i32 @_ZN1A1nEi.llvm. +; OPT-INDEX1: declare void @_ZN1A1nEi.llvm. + +; OPT-INDEX2: ptr @_ZN1A1nEi.llvm. +; OPT-INDEX2: define hidden i32 @_ZN1A1nEi.llvm. +; OPT-INDEX2: tail call i32 @_ZN1A1nEi.llvm. + +;--- a.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +%struct.A = type { ptr } + +define i32 @test(ptr %obj, i32 %a) { +entry: + %vtable = load ptr, ptr %obj + %p = call i1 @llvm.type.test(ptr %vtable, metadata !"_ZTS1A") + call void @llvm.assume(i1 %p) + %fptrptr = getelementptr ptr, ptr %vtable, i32 1 + %fptr1 = load ptr, ptr %fptrptr, align 8 + + ; the call was devirtualized. + %call = tail call i32 %fptr1(ptr nonnull %obj, i32 %a) + ret i32 %call +} + +declare i1 @llvm.type.test(ptr, metadata) +declare void @llvm.assume(i1) + +;--- b.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +%struct.A = type { ptr } +%struct.B = type { %struct.A } + +@_ZTV1B = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr poison, ptr @_ZN1B1fEi, ptr @_ZN1A1nEi] }, !type !0, !type !1 + +define i32 @_ZN1B1fEi(ptr %this, i32 %a) #0 { + ret i32 0; +} + +define internal i32 @_ZN1A1nEi(ptr %this, i32 %a) #0 { + ret i32 0; +} + +define i32 @test2(ptr %obj, i32 %a) { +entry: + %vtable2 = load ptr, ptr %obj + %p2 = call i1 @llvm.type.test(ptr %vtable2, metadata !"_ZTS1B") + call void @llvm.assume(i1 %p2) + + %fptrptr = getelementptr ptr, ptr %vtable2, i32 1 + %fptr33 = load ptr, ptr %fptrptr, align 8 + + %call4 = tail call i32 %fptr33(ptr nonnull %obj, i32 %a) + ret i32 %call4 +} + +attributes #0 = { noinline optnone } + +declare i1 @llvm.type.test(ptr, metadata) +declare void @llvm.assume(i1) + +!0 = !{i64 16, !"_ZTS1A"} +!1 = !{i64 16, !"_ZTS1B"} diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll new file mode 100644 index 0000000000000..cc7596c2fb385 --- /dev/null +++ b/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll @@ -0,0 +1,46 @@ +; Two same-name same-file static functions, meaning that they have the same GUID, +; are in both modules respectively. +; This is to test the support for avoiding always renaming, and ensure that +; one copy is still renamed despite the GUID conflict. + +; RUN: opt -thinlto-bc %s -o %t1.bc +; RUN: opt -thinlto-bc %p/Inputs/reduce-promotion-same-file-local-name.ll -o %t2.bc +; +; RUN: llvm-lto2 run %t1.bc %t2.bc \ +; RUN: --whole-program-visibility-enabled-in-lto=true \ +; RUN: -always-rename-promoted-locals=false \ +; RUN: -save-temps -o %t3 \ +; RUN: -r %t1.bc,m1,px \ +; RUN: -r %t2.bc,m2,p \ +; RUN: -r %t1.bc,m2,x +; RUN: llvm-dis %t3.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 +; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 +; +; IMPORT1: define dso_local i32 @m1( +; IMPORT1: tail call fastcc i32 @foo.{{[0-9]+}}( +; IMPORT1: define available_externally i32 @m2( +; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( +; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( + +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-pc-linux-gnu" + +source_filename = "foo.c" + +define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { + %2 = shl nsw i32 %0, 1 + %3 = tail call fastcc i32 @foo(i32 noundef %2) + %4 = tail call i32 @m2(i32 noundef %0) + %5 = add nsw i32 %4, %3 + ret i32 %5 +} + +define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { + %2 = add nsw i32 %0, 5 + %3 = sdiv i32 %2, %0 + ret i32 %3 +} + +declare i32 @m2(i32 noundef) local_unnamed_addr + +attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll new file mode 100644 index 0000000000000..9ddcae6e7bc6d --- /dev/null +++ b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll @@ -0,0 +1,69 @@ +; This is to test the support for avoiding always renaming, and ensure that +; one copy is still renamed despite having different GUIDs. + +; Set up +; RUN: rm -rf %t +; RUN: mkdir -p %t +; RUN: split-file %s %t + +; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc +; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc +; +; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ +; RUN: --whole-program-visibility-enabled-in-lto=true \ +; RUN: -always-rename-promoted-locals=false \ +; RUN: -save-temps -o %t/lto-out \ +; RUN: -r %t/a.bc,m1,px \ +; RUN: -r %t/b.bc,m2,p \ +; RUN: -r %t/a.bc,m2,x +; RUN: llvm-dis %t/lto-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 +; RUN: llvm-dis %t/lto-out.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 +; +; IMPORT1: define dso_local i32 @m1( +; IMPORT1: tail call fastcc i32 @foo.{{[0-9]+}}( +; IMPORT1: define available_externally i32 @m2( +; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( +; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( + +;--- a.ll +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-pc-linux-gnu" + +define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { + %2 = shl nsw i32 %0, 1 + %3 = tail call fastcc i32 @foo(i32 noundef %2) + %4 = tail call i32 @m2(i32 noundef %0) + %5 = add nsw i32 %4, %3 + ret i32 %5 +} + +define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { + %2 = add nsw i32 %0, 5 + %3 = sdiv i32 %2, %0 + ret i32 %3 +} + +declare i32 @m2(i32 noundef) local_unnamed_addr + +attributes #1 = { noinline } + +;--- b.ll +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-pc-linux-gnu" + +; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable +define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { + %2 = tail call fastcc i32 @foo(i32 noundef %0) + %3 = shl nsw i32 %0, 1 + %4 = tail call fastcc i32 @foo(i32 noundef %3) + %5 = add nsw i32 %4, %2 + ret i32 %5 +} + +define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { + %2 = add nsw i32 %0, 5 + %3 = sdiv i32 %2, %0 + ret i32 %3 +} + +attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/reduce-promotion.ll b/llvm/test/ThinLTO/X86/reduce-promotion.ll new file mode 100644 index 0000000000000..e8900c365675b --- /dev/null +++ b/llvm/test/ThinLTO/X86/reduce-promotion.ll @@ -0,0 +1,56 @@ +; Test a simple cross module promotion where the suffix '.llvm.<...>' is not needed +; because when avoiding always renaming, we should detect that there is a single +; version of local foo which doesn't need renaming. + +; Set up +; RUN: rm -rf %t +; RUN: mkdir -p %t +; RUN: split-file %s %t + +; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc +; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc +; +; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ +; RUN: --whole-program-visibility-enabled-in-lto=true \ +; RUN: -always-rename-promoted-locals=false \ +; RUN: -save-temps -o %t/lto-out \ +; RUN: -r %t/a.bc,m1,px \ +; RUN: -r %t/b.bc,m2,p \ +; RUN: -r %t/a.bc,m2,x +; RUN: llvm-dis %t/lto-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 +; RUN: llvm-dis %t/lto-out.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 +; +; IMPORT1: define available_externally i32 @m2( +; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( +; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( + +;--- a.ll +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-pc-linux-gnu" + +define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { + %2 = tail call i32 @m2(i32 noundef %0) + ret i32 %2 +} + +declare i32 @m2(i32 noundef) local_unnamed_addr + +;--- b.ll +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-pc-linux-gnu" + +define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { + %2 = tail call fastcc i32 @foo(i32 noundef %0) + %3 = shl nsw i32 %0, 1 + %4 = tail call fastcc i32 @foo(i32 noundef %3) + %5 = add nsw i32 %4, %2 + ret i32 %5 +} + +define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { + %2 = add nsw i32 %0, 5 + %3 = sdiv i32 %2, %0 + ret i32 %3 +} + +attributes #1 = { noinline } diff --git a/llvm/test/Transforms/LowerTypeTests/import-unsat.ll b/llvm/test/Transforms/LowerTypeTests/import-unsat.ll index f766c2d324163..578e7db70675c 100644 --- a/llvm/test/Transforms/LowerTypeTests/import-unsat.ll +++ b/llvm/test/Transforms/LowerTypeTests/import-unsat.ll @@ -11,6 +11,7 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 0 +; SUMMARY-NEXT: RenameOnPromotion: false ; SUMMARY-NEXT: TypeTests: [ 123 ] ; SUMMARY-NEXT: TypeIdMap: ; SUMMARY-NEXT: typeid1: diff --git a/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml b/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml index 22533ed636a50..97688cc6d8fc8 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml +++ b/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml @@ -26,6 +26,7 @@ GlobalValueMap: 43: - Live: true ImportType : 1 + NoRenameOnPromotion: true TypeIdMap: typeid1: WPDRes: diff --git a/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll b/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll index 2c33059b6e126..779ca8f690288 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll +++ b/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll @@ -11,6 +11,7 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 0 +; SUMMARY-NEXT: NoRenameOnPromotion: false ; SUMMARY-NEXT: TypeTestAssumeVCalls: ; SUMMARY-NEXT: - GUID: 123 ; SUMMARY-NEXT: Offset: 0 @@ -39,6 +40,7 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 1 +; SUMMARY-NEXT: NoRenameOnPromotion: true ; SUMMARY-NEXT: TypeIdMap: ; SUMMARY-NEXT: typeid1: ; SUMMARY-NEXT: TTRes: From 729602e81009460a67dae3b8d1d8466b3c83211d Mon Sep 17 00:00:00 2001 From: Nick Sarnie Date: Sat, 28 Feb 2026 02:18:55 +0900 Subject: [PATCH 04/58] Revert "[SPIRV][NFCI] Use unordered data structures for SPIR-V extensions" (#183774) Reverts llvm/llvm-project#183567 UBSan failure. --- .../Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h | 23 -- llvm/lib/Target/SPIRV/SPIRVAPI.cpp | 2 +- llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 333 +++++++++--------- llvm/lib/Target/SPIRV/SPIRVCommandLine.h | 19 +- llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp | 10 +- llvm/lib/Target/SPIRV/SPIRVSubtarget.h | 8 +- 6 files changed, 197 insertions(+), 198 deletions(-) diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h index 9b186e2973174..ea41716bf204e 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h @@ -15,12 +15,10 @@ #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVSYMBOLICOPERANDS_H #define LLVM_LIB_TARGET_SPIRV_SPIRVSYMBOLICOPERANDS_H -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/VersionTuple.h" #include -#include namespace llvm { namespace SPIRV { @@ -258,27 +256,6 @@ using CapabilityList = SmallVector; using ExtensionList = SmallVector; using EnvironmentList = SmallVector; -// Tablegen enum types don't have an underlying type which is required for -// DenseMap so just use the DenseMapInfo for std::underlying_type_t. -template <> struct DenseMapInfo { - using DMI = DenseMapInfo>; - static SPIRV::Extension::Extension getEmptyKey() { - return static_cast(DMI::getEmptyKey()); - } - static SPIRV::Extension::Extension getTombstoneKey() { - return static_cast(DMI::getTombstoneKey()); - } - static unsigned getHashValue(SPIRV::Extension::Extension Ty) { - return DMI::getHashValue(Ty); - } - static bool isEqual(SPIRV::Extension::Extension Ty1, - SPIRV::Extension::Extension Ty2) { - return Ty1 == Ty2; - } -}; - -using ExtensionSet = DenseSet; - std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value); diff --git a/llvm/lib/Target/SPIRV/SPIRVAPI.cpp b/llvm/lib/Target/SPIRV/SPIRVAPI.cpp index ab3c1c09fd819..d6581b274e00f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAPI.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAPI.cpp @@ -59,7 +59,7 @@ SPIRVTranslate(Module *M, std::string &SpirvObj, std::string &ErrMsg, static const std::string DefaultTriple = "spirv64-unknown-unknown"; static const std::string DefaultMArch = ""; - ExtensionSet AllowedExtIds; + std::set AllowedExtIds; StringRef UnknownExt = SPIRVExtensionsParser::checkExtensions(AllowExtNames, AllowedExtIds); if (!UnknownExt.empty()) { diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 33e1b52b724e6..31c7a61e1a3d8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -14,11 +14,12 @@ #include "SPIRVCommandLine.h" #include "MCTargetDesc/SPIRVBaseInfo.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" #include "llvm/TargetParser/Triple.h" #include #include +#include +#include #include #include #include @@ -27,167 +28,178 @@ using namespace llvm; -ExtensionSet SPIRVExtensionsParser::DisabledExtensions; +std::set SPIRVExtensionsParser::DisabledExtensions; -static const StringMap SPIRVExtensionMap = { - {"SPV_EXT_shader_atomic_float_add", - SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add}, - {"SPV_EXT_shader_atomic_float16_add", - SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add}, - {"SPV_EXT_shader_atomic_float_min_max", - SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, - {"SPV_INTEL_16bit_atomics", - SPIRV::Extension::Extension::SPV_INTEL_16bit_atomics}, - {"SPV_NV_shader_atomic_fp16_vector", - SPIRV::Extension::Extension::SPV_NV_shader_atomic_fp16_vector}, - {"SPV_EXT_arithmetic_fence", - SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence}, - {"SPV_EXT_demote_to_helper_invocation", - SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}, - {"SPV_EXT_descriptor_indexing", - SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing}, - {"SPV_EXT_fragment_fully_covered", - SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered}, - {"SPV_EXT_fragment_invocation_density", - SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density}, - {"SPV_EXT_fragment_shader_interlock", - SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock}, - {"SPV_EXT_mesh_shader", SPIRV::Extension::Extension::SPV_EXT_mesh_shader}, - {"SPV_EXT_shader_stencil_export", - SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export}, - {"SPV_EXT_shader_viewport_index_layer", - SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer}, - {"SPV_GOOGLE_hlsl_functionality1", - SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1}, - {"SPV_GOOGLE_user_type", SPIRV::Extension::Extension::SPV_GOOGLE_user_type}, - {"SPV_ALTERA_arbitrary_precision_integers", - SPIRV::Extension::Extension::SPV_ALTERA_arbitrary_precision_integers}, - {"SPV_ALTERA_arbitrary_precision_floating_point", - SPIRV::Extension::Extension:: - SPV_ALTERA_arbitrary_precision_floating_point}, - {"SPV_INTEL_cache_controls", - SPIRV::Extension::Extension::SPV_INTEL_cache_controls}, - {"SPV_INTEL_float_controls2", - SPIRV::Extension::Extension::SPV_INTEL_float_controls2}, - {"SPV_INTEL_global_variable_fpga_decorations", - SPIRV::Extension::Extension::SPV_INTEL_global_variable_fpga_decorations}, - {"SPV_INTEL_global_variable_host_access", - SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access}, - {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, - {"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone}, - {"SPV_INTEL_usm_storage_classes", - SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, - {"SPV_INTEL_split_barrier", - SPIRV::Extension::Extension::SPV_INTEL_split_barrier}, - {"SPV_INTEL_subgroups", SPIRV::Extension::Extension::SPV_INTEL_subgroups}, - {"SPV_INTEL_media_block_io", - SPIRV::Extension::Extension::SPV_INTEL_media_block_io}, - {"SPV_INTEL_memory_access_aliasing", - SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing}, - {"SPV_INTEL_joint_matrix", - SPIRV::Extension::Extension::SPV_INTEL_joint_matrix}, - {"SPV_KHR_16bit_storage", - SPIRV::Extension::Extension::SPV_KHR_16bit_storage}, - {"SPV_KHR_device_group", SPIRV::Extension::Extension::SPV_KHR_device_group}, - {"SPV_KHR_fragment_shading_rate", - SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate}, - {"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview}, - {"SPV_KHR_post_depth_coverage", - SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage}, - {"SPV_KHR_shader_draw_parameters", - SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters}, - {"SPV_KHR_ray_tracing", SPIRV::Extension::Extension::SPV_KHR_ray_tracing}, - {"SPV_KHR_uniform_group_instructions", - SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions}, - {"SPV_KHR_no_integer_wrap_decoration", - SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration}, - {"SPV_KHR_float_controls", - SPIRV::Extension::Extension::SPV_KHR_float_controls}, - {"SPV_KHR_expect_assume", - SPIRV::Extension::Extension::SPV_KHR_expect_assume}, - {"SPV_KHR_bit_instructions", - SPIRV::Extension::Extension::SPV_KHR_bit_instructions}, - {"SPV_KHR_integer_dot_product", - SPIRV::Extension::Extension::SPV_KHR_integer_dot_product}, - {"SPV_KHR_linkonce_odr", SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, - {"SPV_KHR_fma", SPIRV::Extension::Extension::SPV_KHR_fma}, - {"SPV_INTEL_inline_assembly", - SPIRV::Extension::Extension::SPV_INTEL_inline_assembly}, - {"SPV_INTEL_bindless_images", - SPIRV::Extension::Extension::SPV_INTEL_bindless_images}, - {"SPV_INTEL_bfloat16_arithmetic", - SPIRV::Extension::Extension::SPV_INTEL_bfloat16_arithmetic}, - {"SPV_INTEL_bfloat16_conversion", - SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, - {"SPV_KHR_subgroup_rotate", - SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate}, - {"SPV_INTEL_variable_length_array", - SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, - {"SPV_INTEL_function_pointers", - SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, - {"SPV_KHR_shader_clock", SPIRV::Extension::Extension::SPV_KHR_shader_clock}, - {"SPV_KHR_cooperative_matrix", - SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, - {"SPV_KHR_non_semantic_info", - SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}, - {"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query}, - {"SPV_EXT_shader_image_int64", - SPIRV::Extension::Extension::SPV_EXT_shader_image_int64}, - {"SPV_KHR_fragment_shader_barycentric", - SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric}, - {"SPV_KHR_physical_storage_buffer", - SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer}, - {"SPV_KHR_vulkan_memory_model", - SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model}, - {"SPV_NV_shader_subgroup_partitioned", - SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned}, - {"SPV_INTEL_long_composites", - SPIRV::Extension::Extension::SPV_INTEL_long_composites}, - {"SPV_INTEL_fp_max_error", - SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}, - {"SPV_INTEL_subgroup_matrix_multiply_accumulate", - SPIRV::Extension::Extension:: - SPV_INTEL_subgroup_matrix_multiply_accumulate}, - {"SPV_INTEL_ternary_bitwise_function", - SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function}, - {"SPV_INTEL_2d_block_io", - SPIRV::Extension::Extension::SPV_INTEL_2d_block_io}, - {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4}, - {"SPV_KHR_float_controls2", - SPIRV::Extension::Extension::SPV_KHR_float_controls2}, - {"SPV_INTEL_tensor_float32_conversion", - SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}, - {"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16}, - {"SPV_EXT_relaxed_printf_string_address_space", - SPIRV::Extension::Extension::SPV_EXT_relaxed_printf_string_address_space}, - {"SPV_INTEL_predicated_io", - SPIRV::Extension::Extension::SPV_INTEL_predicated_io}, - {"SPV_KHR_maximal_reconvergence", - SPIRV::Extension::Extension::SPV_KHR_maximal_reconvergence}, - {"SPV_INTEL_kernel_attributes", - SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes}, - {"SPV_ALTERA_blocking_pipes", - SPIRV::Extension::Extension::SPV_ALTERA_blocking_pipes}, - {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4}, - {"SPV_ALTERA_arbitrary_precision_fixed_point", - SPIRV::Extension::Extension::SPV_ALTERA_arbitrary_precision_fixed_point}, - {"SPV_EXT_image_raw10_raw12", - SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12}, - {"SPV_INTEL_unstructured_loop_controls", - SPIRV::Extension::Extension::SPV_INTEL_unstructured_loop_controls}}; +static const std::map + SPIRVExtensionMap = { + {"SPV_EXT_shader_atomic_float_add", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add}, + {"SPV_EXT_shader_atomic_float16_add", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add}, + {"SPV_EXT_shader_atomic_float_min_max", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, + {"SPV_INTEL_16bit_atomics", + SPIRV::Extension::Extension::SPV_INTEL_16bit_atomics}, + {"SPV_NV_shader_atomic_fp16_vector", + SPIRV::Extension::Extension::SPV_NV_shader_atomic_fp16_vector}, + {"SPV_EXT_arithmetic_fence", + SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence}, + {"SPV_EXT_demote_to_helper_invocation", + SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}, + {"SPV_EXT_descriptor_indexing", + SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing}, + {"SPV_EXT_fragment_fully_covered", + SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered}, + {"SPV_EXT_fragment_invocation_density", + SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density}, + {"SPV_EXT_fragment_shader_interlock", + SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock}, + {"SPV_EXT_mesh_shader", + SPIRV::Extension::Extension::SPV_EXT_mesh_shader}, + {"SPV_EXT_shader_stencil_export", + SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export}, + {"SPV_EXT_shader_viewport_index_layer", + SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer}, + {"SPV_GOOGLE_hlsl_functionality1", + SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1}, + {"SPV_GOOGLE_user_type", + SPIRV::Extension::Extension::SPV_GOOGLE_user_type}, + {"SPV_ALTERA_arbitrary_precision_integers", + SPIRV::Extension::Extension::SPV_ALTERA_arbitrary_precision_integers}, + {"SPV_ALTERA_arbitrary_precision_floating_point", + SPIRV::Extension::Extension:: + SPV_ALTERA_arbitrary_precision_floating_point}, + {"SPV_INTEL_cache_controls", + SPIRV::Extension::Extension::SPV_INTEL_cache_controls}, + {"SPV_INTEL_float_controls2", + SPIRV::Extension::Extension::SPV_INTEL_float_controls2}, + {"SPV_INTEL_global_variable_fpga_decorations", + SPIRV::Extension::Extension:: + SPV_INTEL_global_variable_fpga_decorations}, + {"SPV_INTEL_global_variable_host_access", + SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access}, + {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, + {"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone}, + {"SPV_INTEL_usm_storage_classes", + SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, + {"SPV_INTEL_split_barrier", + SPIRV::Extension::Extension::SPV_INTEL_split_barrier}, + {"SPV_INTEL_subgroups", + SPIRV::Extension::Extension::SPV_INTEL_subgroups}, + {"SPV_INTEL_media_block_io", + SPIRV::Extension::Extension::SPV_INTEL_media_block_io}, + {"SPV_INTEL_memory_access_aliasing", + SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing}, + {"SPV_INTEL_joint_matrix", + SPIRV::Extension::Extension::SPV_INTEL_joint_matrix}, + {"SPV_KHR_16bit_storage", + SPIRV::Extension::Extension::SPV_KHR_16bit_storage}, + {"SPV_KHR_device_group", + SPIRV::Extension::Extension::SPV_KHR_device_group}, + {"SPV_KHR_fragment_shading_rate", + SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate}, + {"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview}, + {"SPV_KHR_post_depth_coverage", + SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage}, + {"SPV_KHR_shader_draw_parameters", + SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters}, + {"SPV_KHR_ray_tracing", + SPIRV::Extension::Extension::SPV_KHR_ray_tracing}, + {"SPV_KHR_uniform_group_instructions", + SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions}, + {"SPV_KHR_no_integer_wrap_decoration", + SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration}, + {"SPV_KHR_float_controls", + SPIRV::Extension::Extension::SPV_KHR_float_controls}, + {"SPV_KHR_expect_assume", + SPIRV::Extension::Extension::SPV_KHR_expect_assume}, + {"SPV_KHR_bit_instructions", + SPIRV::Extension::Extension::SPV_KHR_bit_instructions}, + {"SPV_KHR_integer_dot_product", + SPIRV::Extension::Extension::SPV_KHR_integer_dot_product}, + {"SPV_KHR_linkonce_odr", + SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, + {"SPV_KHR_fma", SPIRV::Extension::Extension::SPV_KHR_fma}, + {"SPV_INTEL_inline_assembly", + SPIRV::Extension::Extension::SPV_INTEL_inline_assembly}, + {"SPV_INTEL_bindless_images", + SPIRV::Extension::Extension::SPV_INTEL_bindless_images}, + {"SPV_INTEL_bfloat16_arithmetic", + SPIRV::Extension::Extension::SPV_INTEL_bfloat16_arithmetic}, + {"SPV_INTEL_bfloat16_conversion", + SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, + {"SPV_KHR_subgroup_rotate", + SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate}, + {"SPV_INTEL_variable_length_array", + SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, + {"SPV_INTEL_function_pointers", + SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, + {"SPV_KHR_shader_clock", + SPIRV::Extension::Extension::SPV_KHR_shader_clock}, + {"SPV_KHR_cooperative_matrix", + SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, + {"SPV_KHR_non_semantic_info", + SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}, + {"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query}, + {"SPV_EXT_shader_image_int64", + SPIRV::Extension::Extension::SPV_EXT_shader_image_int64}, + {"SPV_KHR_fragment_shader_barycentric", + SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric}, + {"SPV_KHR_physical_storage_buffer", + SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer}, + {"SPV_KHR_vulkan_memory_model", + SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model}, + {"SPV_NV_shader_subgroup_partitioned", + SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned}, + {"SPV_INTEL_long_composites", + SPIRV::Extension::Extension::SPV_INTEL_long_composites}, + {"SPV_INTEL_fp_max_error", + SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}, + {"SPV_INTEL_subgroup_matrix_multiply_accumulate", + SPIRV::Extension::Extension:: + SPV_INTEL_subgroup_matrix_multiply_accumulate}, + {"SPV_INTEL_ternary_bitwise_function", + SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function}, + {"SPV_INTEL_2d_block_io", + SPIRV::Extension::Extension::SPV_INTEL_2d_block_io}, + {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4}, + {"SPV_KHR_float_controls2", + SPIRV::Extension::Extension::SPV_KHR_float_controls2}, + {"SPV_INTEL_tensor_float32_conversion", + SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}, + {"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16}, + {"SPV_EXT_relaxed_printf_string_address_space", + SPIRV::Extension::Extension:: + SPV_EXT_relaxed_printf_string_address_space}, + {"SPV_INTEL_predicated_io", + SPIRV::Extension::Extension::SPV_INTEL_predicated_io}, + {"SPV_KHR_maximal_reconvergence", + SPIRV::Extension::Extension::SPV_KHR_maximal_reconvergence}, + {"SPV_INTEL_kernel_attributes", + SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes}, + {"SPV_ALTERA_blocking_pipes", + SPIRV::Extension::Extension::SPV_ALTERA_blocking_pipes}, + {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4}, + {"SPV_ALTERA_arbitrary_precision_fixed_point", + SPIRV::Extension::Extension:: + SPV_ALTERA_arbitrary_precision_fixed_point}, + {"SPV_EXT_image_raw10_raw12", + SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12}, + {"SPV_INTEL_unstructured_loop_controls", + SPIRV::Extension::Extension::SPV_INTEL_unstructured_loop_controls}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, - StringRef ArgValue, ExtensionSet &Vals) { + StringRef ArgValue, + std::set &Vals) { SmallVector Tokens; ArgValue.split(Tokens, ",", -1, false); - ExtensionSet EnabledExtensions; + std::set EnabledExtensions; auto M = partition(Tokens, [](auto &&T) { return T.starts_with('+'); }); if (std::any_of(M, Tokens.end(), equal_to("all"))) - for (auto &&El : make_second_range(SPIRVExtensionMap)) - Vals.insert(El); + copy(make_second_range(SPIRVExtensionMap), std::inserter(Vals, Vals.end())); for (auto &&Token : make_range(Tokens.begin(), M)) { StringRef ExtensionName = Token.substr(1); @@ -215,24 +227,24 @@ bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, auto NameValuePair = SPIRVExtensionMap.find(Token.substr(1)); - if (NameValuePair == SPIRVExtensionMap.end()) + if (NameValuePair == SPIRVExtensionMap.cend()) return O.error("Unknown SPIR-V extension: " + Token.str()); if (EnabledExtensions.count(NameValuePair->second)) return O.error( "Extension cannot be allowed and disallowed at the same time: " + - NameValuePair->first()); + NameValuePair->first); DisabledExtensions.insert(NameValuePair->second); Vals.erase(NameValuePair->second); } - Vals.insert(EnabledExtensions.begin(), EnabledExtensions.end()); + Vals.insert(EnabledExtensions.cbegin(), EnabledExtensions.cend()); return false; } -StringRef -SPIRVExtensionsParser::checkExtensions(const std::vector &ExtNames, - ExtensionSet &AllowedExtensions) { +StringRef SPIRVExtensionsParser::checkExtensions( + const std::vector &ExtNames, + std::set &AllowedExtensions) { for (const auto &Ext : ExtNames) { if (Ext == "all") { for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) @@ -247,8 +259,9 @@ SPIRVExtensionsParser::checkExtensions(const std::vector &ExtNames, return StringRef(); } -ExtensionSet SPIRVExtensionsParser::getValidExtensions(const Triple &TT) { - ExtensionSet R; +std::set +SPIRVExtensionsParser::getValidExtensions(const Triple &TT) { + std::set R; SPIRV::Environment::Environment CurrentEnvironment = SPIRV::Environment::Environment::EnvOpenCL; if (TT.getOS() == Triple::Vulkan) diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.h b/llvm/lib/Target/SPIRV/SPIRVCommandLine.h index d0d52eb3a2352..03dba5915d06e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.h +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.h @@ -16,6 +16,7 @@ #include "MCTargetDesc/SPIRVBaseInfo.h" #include "llvm/Support/CommandLine.h" +#include #include namespace llvm { @@ -23,29 +24,33 @@ class StringRef; class Triple; /// Command line parser for toggling SPIR-V extensions. -struct SPIRVExtensionsParser : public cl::parser { +struct SPIRVExtensionsParser + : public cl::parser> { public: - SPIRVExtensionsParser(cl::Option &O) : cl::parser(O) {} + SPIRVExtensionsParser(cl::Option &O) + : cl::parser>(O) {} /// Parses SPIR-V extension name from CLI arguments. /// /// \return Returns true on error. bool parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, - ExtensionSet &Vals); + std::set &Vals); /// Validates and converts extension names into internal enum values. /// /// \return Returns a reference to the unknown SPIR-V extension name from the /// list if present, or an empty StringRef on success. - static StringRef checkExtensions(const std::vector &ExtNames, - ExtensionSet &AllowedExtensions); + static StringRef + checkExtensions(const std::vector &ExtNames, + std::set &AllowedExtensions); /// Returns the list of extensions that are valid for a particular /// target environment (i.e., OpenCL or Vulkan). - static ExtensionSet getValidExtensions(const Triple &TT); + static std::set + getValidExtensions(const Triple &TT); private: - static ExtensionSet DisabledExtensions; + static std::set DisabledExtensions; }; } // namespace llvm diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index d65d8ec53c6d0..63d7100fbf24a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -32,13 +32,15 @@ static cl::opt cl::desc("SPIR-V Translator compatibility mode"), cl::Optional, cl::init(false)); -static cl::opt +static cl::opt, false, + SPIRVExtensionsParser> Extensions("spirv-ext", cl::desc("Specify list of enabled SPIR-V extensions")); // Provides access to the cl::opt<...> `Extensions` variable from outside of the // module. -void SPIRVSubtarget::addExtensionsToClOpt(const ExtensionSet &AllowList) { +void SPIRVSubtarget::addExtensionsToClOpt( + const std::set &AllowList) { Extensions.insert(AllowList.begin(), AllowList.end()); } @@ -212,9 +214,9 @@ void SPIRVSubtarget::resolveEnvFromModule(const Module &M) { // Set available extensions after SPIRVSubtarget is created. void SPIRVSubtarget::initAvailableExtensions( - const ExtensionSet &AllowedExtIds) { + const std::set &AllowedExtIds) { AvailableExtensions.clear(); - const ExtensionSet &ValidExtensions = + const std::set &ValidExtensions = SPIRVExtensionsParser::getValidExtensions(TargetTriple); for (const auto &Ext : AllowedExtIds) { diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h index 1b14a89695f59..18f7e0179270c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h @@ -73,7 +73,8 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo { const std::string &FS, const SPIRVTargetMachine &TM); SPIRVSubtarget &initSubtargetDependencies(StringRef CPU, StringRef FS); - void initAvailableExtensions(const ExtensionSet &AllowedExtIds); + void initAvailableExtensions( + const std::set &AllowedExtIds); void resolveEnvFromModule(const Module &M); // Parses features string setting specified subtarget options. @@ -144,8 +145,9 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo { // Adds known SPIR-V extensions to the global list of allowed extensions that // SPIRVSubtarget module owns as - // cl::opt global variable. - static void addExtensionsToClOpt(const ExtensionSet &AllowList); + // cl::opt, ...> global variable. + static void + addExtensionsToClOpt(const std::set &AllowList); }; } // namespace llvm From a703d91091ec6f61bc044413a2799349b2214a0d Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 27 Feb 2026 09:20:48 -0800 Subject: [PATCH 05/58] [lldb-dap] Improve test performance for 'cancel' request. (#183632) Update the test to more cleanly handle making a 'blocking' call using a custom command instead of python `time.sleep`, which we cannot easily interrupt. This should improve the overall performance of the tests, locally they took around 30s and now finish in around 6s. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 4 +- .../tools/lldb-dap/cancel/TestDAP_cancel.py | 40 +++++++++++-------- .../API/tools/lldb-dap/cancel/busy_loop.py | 17 ++++++++ 3 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/cancel/busy_loop.py diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py index 14a5698653588..8edda1f5a7bd3 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py @@ -241,11 +241,13 @@ def verify_stop_exception_info( def verify_stop_on_entry(self) -> None: """Waits for the process to be stopped and then verifies at least one thread has the stop reason 'entry'.""" + if not self.dap_server.configuration_done_sent: + self.verify_configuration_done() self.dap_server.wait_for_stopped() self.assertIn( "entry", (t["reason"] for t in self.dap_server.thread_stop_reasons.values()), - "Expected at least one thread to report stop reason 'entry' in {self.dap_server.thread_stop_reasons}", + f"Expected at least one thread to report stop reason 'entry' in {self.dap_server.thread_stop_reasons}", ) def verify_commands(self, flavor: str, output: str, commands: List[str]): diff --git a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py index 14789a6694686..67b63df1951f1 100644 --- a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py +++ b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py @@ -2,10 +2,8 @@ Test lldb-dap cancel request """ +import os import time - -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * import lldbdap_testcase @@ -13,25 +11,21 @@ class TestDAP_cancel(lldbdap_testcase.DAPTestCaseBase): def send_async_req(self, command: str, arguments: dict = {}) -> int: return self.dap_server.send_packet( { + "seq": 0, "type": "request", "command": command, "arguments": arguments, } ) - def async_blocking_request(self, duration: float) -> int: + def async_blocking_request(self, count: int) -> int: """ - Sends an evaluate request that will sleep for the specified duration to + Sends an evaluate request that will sleep for the specified count to block the request handling thread. """ return self.send_async_req( command="evaluate", - arguments={ - "expression": '`script import time; print("starting sleep", file=lldb.debugger.GetOutputFileHandle()); time.sleep({})'.format( - duration - ), - "context": "repl", - }, + arguments={"expression": f"`busy-loop {count}", "context": "repl"}, ) def async_cancel(self, requestId: int) -> int: @@ -42,14 +36,20 @@ def test_pending_request(self): Tests cancelling a pending request. """ program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + busy_loop = self.getSourcePath("busy_loop.py") + self.build_and_launch( + program, + initCommands=[f"command script import {busy_loop}"], + stopOnEntry=True, + ) + self.verify_stop_on_entry() # Use a relatively short timeout since this is only to ensure the # following request is queued. - blocking_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 10) + blocking_seq = self.async_blocking_request(count=1) # Use a longer timeout to ensure we catch if the request was interrupted # properly. - pending_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 2) + pending_seq = self.async_blocking_request(count=10) cancel_seq = self.async_cancel(requestId=pending_seq) blocking_resp = self.dap_server.receive_response(blocking_seq) @@ -74,11 +74,17 @@ def test_inflight_request(self): Tests cancelling an inflight request. """ program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + busy_loop = self.getSourcePath("busy_loop.py") + self.build_and_launch( + program, + initCommands=[f"command script import {busy_loop}"], + stopOnEntry=True, + ) + self.verify_stop_on_entry() - blocking_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 2) + blocking_seq = self.async_blocking_request(count=10) # Wait for the sleep to start to cancel the inflight request. - self.collect_console(pattern="starting sleep") + time.sleep(0.5) cancel_seq = self.async_cancel(requestId=blocking_seq) blocking_resp = self.dap_server.receive_response(blocking_seq) diff --git a/lldb/test/API/tools/lldb-dap/cancel/busy_loop.py b/lldb/test/API/tools/lldb-dap/cancel/busy_loop.py new file mode 100644 index 0000000000000..21108d7e32e45 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/cancel/busy_loop.py @@ -0,0 +1,17 @@ +import time +import lldb + + +@lldb.command(command_name="busy-loop") +def busy_loop(debugger, command, exe_ctx, result, internal_dict): + """Test helper as a busy loop.""" + if not command: + command = "10" + count = int(command) + print("Starting loop...", count) + for i in range(count): + if debugger.InterruptRequested(): + print("interrupt requested, stopping loop", i) + break + print("No interrupted requested, sleeping", i) + time.sleep(1) From d1da7f6ee5d7ee8729ade96209d8b19bdef69d52 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Fri, 27 Feb 2026 09:24:04 -0800 Subject: [PATCH 06/58] [clang-scan-deps] Add test for symlink-aliased module map PCM reuse across incremental scans (#183328) Add a test that verifies symlink aliases to a module map directory produce the same PCM across incremental scans. --- ...ules-symlink-dir-from-module-incremental.c | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 clang/test/ClangScanDeps/modules-symlink-dir-from-module-incremental.c diff --git a/clang/test/ClangScanDeps/modules-symlink-dir-from-module-incremental.c b/clang/test/ClangScanDeps/modules-symlink-dir-from-module-incremental.c new file mode 100644 index 0000000000000..9b7a0644b919d --- /dev/null +++ b/clang/test/ClangScanDeps/modules-symlink-dir-from-module-incremental.c @@ -0,0 +1,93 @@ +// Check that symlink aliases to a module map directory produce the same PCM +// across incremental scans. This test was adapted from +// modules-symlink-dir-from-module.c, where a transitive module dependency (Mod) +// is only discoverable through an included header and not from by-name lookup. + +// The first scan builds Mod's PCM via the canonical path. +// The second scan encounters Mod only through a symlinked directory, but +// should reuse the existing PCM rather than rebuilding it with the symlink path +// as the module map file. This is because the PCM filename hash is canonicalized, +// and the module map is resolved through header search so Mod's module map is +// always discoverable regardless of whether it was imported directly or transitively. + +// REQUIRES: symlinks + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json +// RUN: sed -e "s|DIR|%/t|g" %t/cdb_alternate_path.json.in > %t/cdb_alternate_path.json +// RUN: ln -s module %t/include/symlink-to-module + +// RUN: touch %t/session.timestamp + +// RUN: clang-scan-deps -compilation-database %t/cdb.json -j 1 \ +// RUN: -format experimental-full -mode=preprocess-dependency-directives \ +// RUN: -optimize-args=all -module-files-dir %t/build > %t/deps.json + +// RUN: ls %t/module-cache/*/Mod-*.pcm | count 1 +// RUN: %clang -cc1 -module-file-info %t/module-cache/*/Mod-*.pcm 2>&1 | grep "Module map file" | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t + +// RUN: clang-scan-deps -compilation-database %t/cdb_alternate_path.json -j 1 \ +// RUN: -format experimental-full -mode=preprocess-dependency-directives \ +// RUN: -optimize-args=all -module-files-dir %t/build > %t/deps_incremental.json + +// RUN: ls %t/module-cache/*/Mod-*.pcm | count 1 +// RUN: %clang -cc1 -module-file-info %t/module-cache/*/Mod-*.pcm 2>&1 | grep "Module map file" | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t + +/// Verify resulting explicit module remain the same. +// RUN: %deps-to-rsp %t/deps.json --module-name=Mod > %t/Mod.cc1.rsp +// RUN: %deps-to-rsp %t/deps_incremental.json --module-name=Mod > %t/Mod_incremental.cc1.rsp +// RUN: diff %t/Mod.cc1.rsp %t/Mod_incremental.cc1.rsp + +// CHECK: Module map file: [[PREFIX]]/include/module/module.modulemap + +//--- cdb.json.in +[{ + "directory": "DIR", + "command": "clang -fsyntax-only DIR/test.c -F DIR/Frameworks -I DIR/include -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -fbuild-session-file=DIR/session.timestamp -fmodules-validate-once-per-build-session", + "file": "DIR/test.c" +}] + +//--- cdb_alternate_path.json.in +[{ + "directory": "DIR", + "command": "clang -fsyntax-only DIR/test_incremental.c -F DIR/Frameworks -I DIR/include -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -fbuild-session-file=DIR/session.timestamp -fmodules-validate-once-per-build-session", + "file": "DIR/test_incremental.c" +}] + +//--- include/module/module.modulemap +module Mod { header "mod.h" export * } + +//--- include/module/mod.h + +//--- include/module.modulemap +module Other { header "other.h" export * } + +//--- include/other.h +#include "symlink-to-module/mod.h" +#include "module/mod.h" + +//--- Frameworks/Foo.framework/Modules/module.modulemap +framework module Foo { header "Foo.h" export * } +//--- Frameworks/Foo.framework/Modules/module.private.modulemap +framework module Foo_Private { header "Priv.h" export * } + +//--- Frameworks/Foo.framework/Headers/Foo.h +#include "module/mod.h" + +//--- Frameworks/Foo.framework/PrivateHeaders/Priv.h +#include +#include "other.h" + +//--- module.modulemap +module Test { header "test.h" export * } + +//--- test.h +#include +#include + +//--- test.c +#include "test.h" + +//--- test_incremental.c +#include "symlink-to-module/mod.h" From 0617623858054a3533b3ed44d355dee7f9102c1c Mon Sep 17 00:00:00 2001 From: Dmitry Sidorov Date: Fri, 27 Feb 2026 18:24:29 +0100 Subject: [PATCH 07/58] [SPIR-V] Fix non-deterministic compiler output for debug type pointer (#182773) Fixes: https://github.com/llvm/llvm-project/issues/123791 --- .../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp | 6 ++--- .../SPIRV/debug-info/debug-type-pointer.ll | 26 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp index a9208f00c1113..4e4b9fdffa7f0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp @@ -5,7 +5,7 @@ #include "SPIRVRegisterInfo.h" #include "SPIRVTargetMachine.h" #include "SPIRVUtils.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" @@ -94,8 +94,8 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) { SmallVector LLVMSourceLanguages; int64_t DwarfVersion = 0; int64_t DebugInfoVersion = 0; - SmallPtrSet BasicTypes; - SmallPtrSet PointerDerivedTypes; + SetVector BasicTypes; + SetVector PointerDerivedTypes; // Searching through the Module metadata to find nescessary // information like DwarfVersion or SourceLanguage { diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll index d260c9f94d4ad..9cdcd6db6cde8 100644 --- a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll +++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll @@ -30,19 +30,19 @@ ; CHECK-MIR-DAG: [[float:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_float]], [[i32_0]] ; CHECK-MIR-DAG: [[double:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_64]], [[enc_float]], [[i32_0]] ; CHECK-MIR-DAG: [[int:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_signed]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]] -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]] -; CHECK-MIR-DAG: [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0 -; CHECK-MIR-DAG: OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]] +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]] +; CHECK-MIR: [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0 +; CHECK-MIR: OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]] ; CHECK-SPIRV: [[i32type:%[0-9]+]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: [[i32_8:%[0-9]+]] = OpConstant [[i32type]] 8{{$}} From de4a1a77e1476e9105a6143a8d3b8760b61ff95f Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 27 Feb 2026 09:36:14 -0800 Subject: [PATCH 08/58] [clang][modules] Prevent deadlock in module cache (#182722) When there's a dependency cycle between modules, the dependency scanner may encounter a deadlock. This was caused by not respecting the lock timeout. But even with the timeout implemented, leaving `unsafeMaybeUnlock()` unimplemented means trying to take a lock after a timeout would still fail and prevent making progress. This PR implements this API in a way to avoid UB on `std::mutex` (when it's unlocked by someone else than the owner). Lastly, this PR makes sure that `unsafeUnlock()` ends the wait of existing threads, so that they don't need to hit the full timeout amount. This PR also implements `-fimplicit-modules-lock-timeout=` that allows tweaking the default 90-second lock timeout, and adds `#pragma clang __debug sleep` that makes it easier to achieve desired execution ordering. rdar://170738600 --- .../DependencyScanning/InProcessModuleCache.h | 8 ++- .../include/clang/Frontend/FrontendOptions.h | 3 + clang/include/clang/Options/Options.td | 6 ++ .../InProcessModuleCache.cpp | 67 ++++++++++++------- clang/lib/Driver/ToolChains/Clang.cpp | 2 + clang/lib/Frontend/CompilerInstance.cpp | 8 ++- clang/lib/Lex/Pragma.cpp | 3 + .../ClangScanDeps/modules-cycle-deadlock.c | 37 ++++++++++ clang/test/Modules/implicit-cycle-deadlock.c | 36 ++++++++++ llvm/include/llvm/Support/AdvisoryLock.h | 2 +- llvm/include/llvm/Support/LockFileManager.h | 2 +- llvm/lib/Support/LockFileManager.cpp | 2 +- llvm/lib/Support/VirtualOutputBackends.cpp | 6 +- llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp | 2 +- 14 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 clang/test/ClangScanDeps/modules-cycle-deadlock.c create mode 100644 clang/test/Modules/implicit-cycle-deadlock.c diff --git a/clang/include/clang/DependencyScanning/InProcessModuleCache.h b/clang/include/clang/DependencyScanning/InProcessModuleCache.h index 4c95171a2e21e..8ad9811606611 100644 --- a/clang/include/clang/DependencyScanning/InProcessModuleCache.h +++ b/clang/include/clang/DependencyScanning/InProcessModuleCache.h @@ -13,14 +13,18 @@ #include "llvm/ADT/StringMap.h" #include +#include #include -#include namespace clang { namespace dependencies { struct ModuleCacheEntry { - std::shared_mutex CompilationMutex; + std::mutex Mutex; + std::condition_variable CondVar; + bool Locked = false; + unsigned Generation = 0; + std::atomic Timestamp = 0; }; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 9a7fdf5cbcf06..9e05181ac916c 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -495,6 +495,9 @@ class FrontendOptions { /// The list of files to embed into the compiled module file. std::vector ModulesEmbedFiles; + /// The time in seconds to wait on an implicit module lock before timing out. + unsigned ImplicitModulesLockTimeoutSeconds = 90; + /// The list of AST files to merge. std::vector ASTMergeFiles; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 5c0a6e3c913ea..f024dc4055e22 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -3498,6 +3498,12 @@ def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, CC1Option]>, HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; +def fimplicit_modules_lock_timeout_EQ : Joined<["-"], "fimplicit-modules-lock-timeout=">, + Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, CC1Option]>, + MetaVarName<"">, + HelpText<"Time to wait on an implicit module lock before timing out">, + MarshallingInfoInt, "90">; + defm skip_odr_check_in_gmf : BoolOption<"f", "skip-odr-check-in-gmf", LangOpts<"SkipODRCheckInGMF">, DefaultFalse, PosFlag - using namespace clang; using namespace dependencies; namespace { class ReaderWriterLock : public llvm::AdvisoryLock { - // TODO: Consider using std::atomic::{wait,notify_all} when we move to C++20. - std::unique_lock OwningLock; + ModuleCacheEntry &Entry; + std::optional OwnedGeneration; public: - ReaderWriterLock(std::shared_mutex &Mutex) - : OwningLock(Mutex, std::defer_lock) {} - - Expected tryLock() override { return OwningLock.try_lock(); } + ReaderWriterLock(ModuleCacheEntry &Entry) : Entry(Entry) {} + + Expected tryLock() override { + std::lock_guard Lock(Entry.Mutex); + if (Entry.Locked) + return false; + Entry.Locked = true; + OwnedGeneration = Entry.Generation; + return true; + } llvm::WaitForUnlockResult waitForUnlockFor(std::chrono::seconds MaxSeconds) override { - assert(!OwningLock); - // We do not respect the timeout here. It's very generous for implicit - // modules, so we'd typically only reach it if the owner crashed (but so did - // we, since we run in the same process), or encountered deadlock. - (void)MaxSeconds; - std::shared_lock Lock(*OwningLock.mutex()); - return llvm::WaitForUnlockResult::Success; + assert(!OwnedGeneration); + std::unique_lock Lock(Entry.Mutex); + unsigned CurrentGeneration = Entry.Generation; + bool Success = Entry.CondVar.wait_for(Lock, MaxSeconds, [&] { + // We check not only Locked, but also Generation to break the wait in case + // of unsafeUnlock() and successful tryLock(). + return !Entry.Locked || Entry.Generation != CurrentGeneration; + }); + return Success ? llvm::WaitForUnlockResult::Success + : llvm::WaitForUnlockResult::Timeout; } - std::error_code unsafeMaybeUnlock() override { - // Unlocking the mutex here would trigger UB and we don't expect this to be - // actually called when compiling scanning modules due to the no-timeout - // guarantee above. + std::error_code unsafeUnlock() override { + { + std::lock_guard Lock(Entry.Mutex); + Entry.Generation += 1; + Entry.Locked = false; + } + Entry.CondVar.notify_all(); return {}; } - ~ReaderWriterLock() override = default; + ~ReaderWriterLock() override { + if (OwnedGeneration) { + { + std::lock_guard Lock(Entry.Mutex); + // Avoid stomping over the state managed by someone else after + // unsafeUnlock() and successful tryLock(). + if (*OwnedGeneration == Entry.Generation) + Entry.Locked = false; + } + Entry.CondVar.notify_all(); + } + } }; class InProcessModuleCache : public ModuleCache { @@ -64,14 +85,14 @@ class InProcessModuleCache : public ModuleCache { void prepareForGetLock(StringRef Filename) override {} std::unique_ptr getLock(StringRef Filename) override { - auto &CompilationMutex = [&]() -> std::shared_mutex & { + auto &Entry = [&]() -> ModuleCacheEntry & { std::lock_guard Lock(Entries.Mutex); auto &Entry = Entries.Map[Filename]; if (!Entry) Entry = std::make_unique(); - return Entry->CompilationMutex; + return *Entry; }(); - return std::make_unique(CompilationMutex); + return std::make_unique(Entry); } std::time_t getModuleTimestamp(StringRef Filename) override { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 29d98e88800da..17ba832bdeb56 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3912,6 +3912,8 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, Path.insert(Path.begin(), Arg, Arg + strlen(Arg)); CmdArgs.push_back(Args.MakeArgString(Path)); } + + Args.AddLastArg(CmdArgs, options::OPT_fimplicit_modules_lock_timeout_EQ); } if (HaveModules) { diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 9f1a3c56feec1..1e256a9d5614c 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1514,7 +1514,9 @@ static bool compileModuleAndReadASTBehindLock( // Someone else is responsible for building the module. Wait for them to // finish. - switch (Lock->waitForUnlockFor(std::chrono::seconds(90))) { + unsigned Timeout = + ImportingInstance.getFrontendOpts().ImplicitModulesLockTimeoutSeconds; + switch (Lock->waitForUnlockFor(std::chrono::seconds(Timeout))) { case llvm::WaitForUnlockResult::Success: break; // The interesting case. case llvm::WaitForUnlockResult::OwnerDied: @@ -1522,11 +1524,11 @@ static bool compileModuleAndReadASTBehindLock( case llvm::WaitForUnlockResult::Timeout: // Since the InMemoryModuleCache takes care of correctness, we try waiting // for someone else to complete the build so that it does not happen - // twice. In case of timeout, build it ourselves. + // twice. In case of timeout, try to build it ourselves again. Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout) << Module->Name; // Clear the lock file so that future invocations can make progress. - Lock->unsafeMaybeUnlock(); + Lock->unsafeUnlock(); continue; } diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index bba3c89bed38f..1a5a6ce61ecf1 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -1079,6 +1080,8 @@ struct PragmaDebugHandler : public PragmaHandler { Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); PP.EnterToken(Crasher, /*IsReinject*/ false); } + } else if (II->isStr("sleep")) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else if (II->isStr("dump")) { Token DumpAnnot; DumpAnnot.startToken(); diff --git a/clang/test/ClangScanDeps/modules-cycle-deadlock.c b/clang/test/ClangScanDeps/modules-cycle-deadlock.c new file mode 100644 index 0000000000000..2a800ff7f2f20 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-cycle-deadlock.c @@ -0,0 +1,37 @@ +// This test checks that implicit modules do not encounter a deadlock on a dependency cycle. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json +// RUN: not clang-scan-deps -mode preprocess -format experimental-full \ +// RUN: -compilation-database %t/cdb.json -j 2 -o %t/out 2> %t/err +// RUN: FileCheck %s --input-file %t/err +// CHECK-DAG: fatal error: cyclic dependency in module 'M': M -> N -> M +// CHECK-DAG: fatal error: cyclic dependency in module 'N': N -> M -> N + +//--- cdb.json.in +[ + { + "file": "DIR/tu1.c", + "directory": "DIR", + "command": "clang -fmodules -fmodules-cache-path=DIR/cache -fimplicit-modules-lock-timeout=3 DIR/tu1.c -o DIR/tu1.o" + }, + { + "file": "DIR/tu2.c", + "directory": "DIR", + "command": "clang -fmodules -fmodules-cache-path=DIR/cache -fimplicit-modules-lock-timeout=3 DIR/tu2.c -o DIR/tu2.o" + } +] +//--- tu1.c +#include "m.h" +//--- tu2.c +#include "n.h" +//--- module.modulemap +module M { header "m.h" } +module N { header "n.h" } +//--- m.h +#pragma clang __debug sleep // Give enough time for tu2.c to start building N. +#include "n.h" +//--- n.h +#pragma clang __debug sleep // Give enough time for tu1.c to start building M. +#include "m.h" diff --git a/clang/test/Modules/implicit-cycle-deadlock.c b/clang/test/Modules/implicit-cycle-deadlock.c new file mode 100644 index 0000000000000..226c80c9b9fa2 --- /dev/null +++ b/clang/test/Modules/implicit-cycle-deadlock.c @@ -0,0 +1,36 @@ +// This test checks that implicit modules do not encounter a deadlock on a dependency cycle. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %python %t/run_concurrently.py \ +// RUN: "not %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/cache -fimplicit-modules-lock-timeout=3 %t/tu1.c 2> %t/err1" \ +// RUN: "not %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/cache -fimplicit-modules-lock-timeout=3 %t/tu2.c 2> %t/err2" + +// RUN: FileCheck %s --input-file %t/err1 --check-prefix=CHECK1 +// RUN: FileCheck %s --input-file %t/err2 --check-prefix=CHECK2 +// CHECK1: fatal error: cyclic dependency in module 'M': M -> N -> M +// CHECK2: fatal error: cyclic dependency in module 'N': N -> M -> N + +//--- run_concurrently.py +import subprocess, sys, threading + +def run(cmd): + subprocess.run(cmd, shell=True) + +threads = [threading.Thread(target=run, args=(cmd,)) for cmd in sys.argv[1:]] +for t in threads: t.start() +for t in threads: t.join() +//--- tu1.c +#include "m.h" +//--- tu2.c +#include "n.h" +//--- module.modulemap +module M { header "m.h" } +module N { header "n.h" } +//--- m.h +#pragma clang __debug sleep // Give enough time for tu2.c to start building N. +#include "n.h" +//--- n.h +#pragma clang __debug sleep // Give enough time for tu1.c to start building M. +#include "m.h" diff --git a/llvm/include/llvm/Support/AdvisoryLock.h b/llvm/include/llvm/Support/AdvisoryLock.h index d1c3ccc187e64..03be1fcbe7243 100644 --- a/llvm/include/llvm/Support/AdvisoryLock.h +++ b/llvm/include/llvm/Support/AdvisoryLock.h @@ -48,7 +48,7 @@ class AdvisoryLock { /// For a lock owned by someone else, unlock it. A permitted side-effect is /// that another thread/process may acquire ownership of the lock before the /// existing owner unlocks it. This is an unsafe operation. - virtual std::error_code unsafeMaybeUnlock() = 0; + virtual std::error_code unsafeUnlock() = 0; /// Unlocks the lock if its ownership was previously acquired by \c tryLock(). virtual ~AdvisoryLock() = default; diff --git a/llvm/include/llvm/Support/LockFileManager.h b/llvm/include/llvm/Support/LockFileManager.h index 1c579ea866f65..69f175bd79f7c 100644 --- a/llvm/include/llvm/Support/LockFileManager.h +++ b/llvm/include/llvm/Support/LockFileManager.h @@ -61,7 +61,7 @@ class LLVM_ABI LockFileManager : public AdvisoryLock { /// Remove the lock file. This may delete a different lock file than /// the one previously read if there is a race. - std::error_code unsafeMaybeUnlock() override; + std::error_code unsafeUnlock() override; /// Unlocks the lock if previously acquired by \c tryLock(). ~LockFileManager() override; diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp index 0891ef980668b..1a98ec03486db 100644 --- a/llvm/lib/Support/LockFileManager.cpp +++ b/llvm/lib/Support/LockFileManager.cpp @@ -294,7 +294,7 @@ LockFileManager::waitForUnlockFor(std::chrono::seconds MaxSeconds) { return WaitForUnlockResult::Timeout; } -std::error_code LockFileManager::unsafeMaybeUnlock() { +std::error_code LockFileManager::unsafeUnlock() { auto BypassSandbox = sys::sandbox::scopedDisable(); return sys::fs::remove(LockFileName); diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp index d7a91dfa1471f..0c6ce825d02d0 100644 --- a/llvm/lib/Support/VirtualOutputBackends.cpp +++ b/llvm/lib/Support/VirtualOutputBackends.cpp @@ -496,7 +496,7 @@ Error OnDiskOutputFile::keep() { if (Error Err = Lock.tryLock().moveInto(Owned)) { // If we error acquiring a lock, we cannot ensure appends // to the trace file are atomic - cannot ensure output correctness. - Lock.unsafeMaybeUnlock(); + Lock.unsafeUnlock(); return convertToOutputError( OutputPath, std::make_error_code(std::errc::no_lock_available)); } @@ -508,7 +508,7 @@ Error OnDiskOutputFile::keep() { return convertToOutputError(OutputPath, EC); Out << (*Content)->getBuffer(); Out.close(); - Lock.unsafeMaybeUnlock(); + Lock.unsafeUnlock(); if (Out.has_error()) return convertToOutputError(OutputPath, Out.error()); // Remove temp file and done. @@ -528,7 +528,7 @@ Error OnDiskOutputFile::keep() { // the lock, causing other waiting processes to time-out. Let's clear // the lock and try again right away. If we do start seeing compiler // hangs in this location, we will need to re-consider. - Lock.unsafeMaybeUnlock(); + Lock.unsafeUnlock(); continue; } } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp index d04dc3e25f2dc..c155d85df1769 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSplitModule.cpp @@ -1575,7 +1575,7 @@ PreservedAnalyses AMDGPUSplitModulePass::run(Module &M, dbgs() << "[amdgpu-split-module] unable to acquire lockfile, debug " "output may be mangled by other processes\n"); - Lock.unsafeMaybeUnlock(); + Lock.unsafeUnlock(); break; // give up } } From 35f8ca8b76c63b47a6c5a7aa041310f42947a838 Mon Sep 17 00:00:00 2001 From: Eugene Epshteyn Date: Fri, 27 Feb 2026 12:41:17 -0500 Subject: [PATCH 09/58] [flang][NFC] Converted five tests from old lowering to new lowering (part 22) (#183681) Tests converted from test/Lower: intentout-deallocate.f90 Tests converted from test/Lower/Intrinsics: abs.f90, achar.f90, acospi.f90, adjustl.f90 --- flang/test/Lower/Intrinsics/abs.f90 | 69 +++++++++------- flang/test/Lower/Intrinsics/achar.f90 | 18 +++-- flang/test/Lower/Intrinsics/acospi.f90 | 15 ++-- flang/test/Lower/Intrinsics/adjustl.f90 | 17 ++-- flang/test/Lower/intentout-deallocate.f90 | 98 +++++++++-------------- 5 files changed, 109 insertions(+), 108 deletions(-) diff --git a/flang/test/Lower/Intrinsics/abs.f90 b/flang/test/Lower/Intrinsics/abs.f90 index 7150cb2d352fd..97c58631a1329 100644 --- a/flang/test/Lower/Intrinsics/abs.f90 +++ b/flang/test/Lower/Intrinsics/abs.f90 @@ -1,22 +1,21 @@ -! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes=CHECK,CMPLX,CMPLX-PRECISE,%if flang-supports-f128-math %{F128%} %else %{F64%} -! RUN: bbc -emit-fir -hlfir=false --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE" -! RUN: bbc --force-mlir-complex -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-FAST" -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,CMPLX,CMPLX-PRECISE,%if flang-supports-f128-math %{F128%} %else %{F64%} -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE" -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mllvm --force-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-FAST" -! RUN: %flang_fc1 -fapprox-func -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-APPROX" +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,CMPLX,CMPLX-PRECISE,%if flang-supports-f128-math %{F128%} %else %{F64%} +! RUN: %flang_fc1 -emit-hlfir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE" +! RUN: %flang_fc1 -emit-hlfir -mllvm --force-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-FAST" +! RUN: %flang_fc1 -fapprox-func -emit-hlfir %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-APPROX" ! Test abs intrinsic for various types (int, float, complex) ! CHECK-LABEL: func @_QPabs_testi ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref subroutine abs_testi(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_3:.*]] = arith.constant 31 : i32 ! CHECK: %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i32 ! CHECK: %[[VAL_5:.*]] = arith.xori %[[VAL_2]], %[[VAL_4]] : i32 ! CHECK: %[[VAL_6:.*]] = arith.subi %[[VAL_5]], %[[VAL_4]] : i32 -! CHECK: fir.store %[[VAL_6]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_1_DECL]]#0 : i32, !fir.ref ! CHECK: return integer :: a, b b = abs(a) @@ -25,12 +24,14 @@ subroutine abs_testi(a, b) ! CHECK-LABEL: func @_QPabs_testi16 ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref subroutine abs_testi16(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_3:.*]] = arith.constant 127 : i128 ! CHECK: %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i128 ! CHECK: %[[VAL_5:.*]] = arith.xori %[[VAL_2]], %[[VAL_4]] : i128 ! CHECK: %[[VAL_6:.*]] = arith.subi %[[VAL_5]], %[[VAL_4]] : i128 -! CHECK: fir.store %[[VAL_6]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_1_DECL]]#0 : i128, !fir.ref ! CHECK: return integer(kind=16) :: a, b b = abs(a) @@ -39,11 +40,13 @@ subroutine abs_testi16(a, b) ! CHECK-LABEL: func @_QPabs_testh( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testh(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_2_1:.*]] = fir.convert %[[VAL_2]] : (f16) -> f32 ! CHECK: %[[VAL_3:.*]] = math.absf %[[VAL_2_1]] {{.*}}: f32 ! CHECK: %[[VAL_3_1:.*]] = fir.convert %[[VAL_3]] : (f32) -> f16 -! CHECK: fir.store %[[VAL_3_1]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_3_1]] to %[[VAL_1_DECL]]#0 : f16, !fir.ref ! CHECK: return real(kind=2) :: a, b b = abs(a) @@ -52,11 +55,13 @@ subroutine abs_testh(a, b) ! CHECK-LABEL: func @_QPabs_testb( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testb(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_2_1:.*]] = fir.convert %[[VAL_2]] : (bf16) -> f32 ! CHECK: %[[VAL_3:.*]] = math.absf %[[VAL_2_1]] {{.*}}: f32 ! CHECK: %[[VAL_3_1:.*]] = fir.convert %[[VAL_3]] : (f32) -> bf16 -! CHECK: fir.store %[[VAL_3_1]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_3_1]] to %[[VAL_1_DECL]]#0 : bf16, !fir.ref ! CHECK: return real(kind=3) :: a, b b = abs(a) @@ -65,9 +70,11 @@ subroutine abs_testb(a, b) ! CHECK-LABEL: func @_QPabs_testr( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testr(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_3:.*]] = math.absf %[[VAL_2]] {{.*}}: f32 -! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_3]] to %[[VAL_1_DECL]]#0 : f32, !fir.ref ! CHECK: return real :: a, b b = abs(a) @@ -76,9 +83,11 @@ subroutine abs_testr(a, b) ! CHECK-LABEL: func @_QPabs_testd( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testd(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! CHECK: %[[VAL_3:.*]] = math.absf %[[VAL_2]] {{.*}}: f64 -! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_3]] to %[[VAL_1_DECL]]#0 : f64, !fir.ref ! CHECK: return real(kind=8) :: a, b b = abs(a) @@ -88,12 +97,14 @@ subroutine abs_testd(a, b) ! F128-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { ! F64-SAME: %[[VAL_0:.*]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testr16(a, b) -! F128: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref -! F64: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! F128: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref +! F64: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref ! F128: %[[VAL_3:.*]] = math.absf %[[VAL_2]] {{.*}}: f128 ! F64: %[[VAL_3:.*]] = math.absf %[[VAL_2]] {{.*}}: f64 -! F128: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref -! F64: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! F128: hlfir.assign %[[VAL_3]] to %[[VAL_1_DECL]]#0 : f128, !fir.ref +! F64: hlfir.assign %[[VAL_3]] to %[[VAL_1_DECL]]#0 : f64, !fir.ref ! CHECK: return integer, parameter :: rk = merge(16, 8, selected_real_kind(33, 4931)==16) real(kind=rk) :: a, b @@ -103,11 +114,13 @@ subroutine abs_testr16(a, b) ! CMPLX-LABEL: func @_QPabs_testzr( ! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testzr(a, b) -! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> +! CMPLX: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CMPLX: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref> ! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_2]] fastmath : complex ! CMPLX-APPROX: %[[VAL_4:.*]] = complex.abs %[[VAL_2]] fastmath : complex ! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabsf(%[[VAL_2]]) {{.*}}: (complex) -> f32 -! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CMPLX: hlfir.assign %[[VAL_4]] to %[[VAL_1_DECL]]#0 : f32, !fir.ref ! CMPLX: return complex :: a real :: b @@ -117,11 +130,13 @@ end subroutine abs_testzr ! CMPLX-LABEL: func @_QPabs_testzd( ! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testzd(a, b) -! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> +! CMPLX: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {{.*}} +! CMPLX: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {{.*}} +! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref> ! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_2]] fastmath : complex ! CMPLX-APPROX: %[[VAL_4:.*]] = complex.abs %[[VAL_2]] fastmath : complex ! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabs(%[[VAL_2]]) {{.*}}: (complex) -> f64 -! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CMPLX: hlfir.assign %[[VAL_4]] to %[[VAL_1_DECL]]#0 : f64, !fir.ref ! CMPLX: return complex(kind=8) :: a real(kind=8) :: b diff --git a/flang/test/Lower/Intrinsics/achar.f90 b/flang/test/Lower/Intrinsics/achar.f90 index 32cf30dde9ab2..27946b4a33440 100644 --- a/flang/test/Lower/Intrinsics/achar.f90 +++ b/flang/test/Lower/Intrinsics/achar.f90 @@ -1,20 +1,24 @@ -! RUN: bbc -emit-fir -hlfir=false %s -o - | fir-opt --canonicalize | FileCheck %s -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | fir-opt --canonicalize | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "x"}, ! CHECK-SAME: %[[VAL_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { -! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1> {adapt.valuebyref} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1> +! CHECK: %[[VAL_D1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref>) -> !fir.ref> -! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_0]] : !fir.ref -! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i8 +! CHECK: %[[VAL_4_DECL:.*]]:2 = hlfir.declare %[[VAL_4]] +! CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_0_DECL]]#0 : !fir.ref +! CHECK: %[[VAL_6_0:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_6_0]] : (i64) -> i8 ! CHECK: %[[VAL_7:.*]] = fir.undefined !fir.char<1> ! CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_6]], [0 : index] : (!fir.char<1>, i8) -> !fir.char<1> ! CHECK: fir.store %[[VAL_8]] to %[[VAL_2]] : !fir.ref> -! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_2]] : !fir.ref> -! CHECK: fir.store %[[VAL_9]] to %[[VAL_4]] : !fir.ref> +! CHECK: %[[VAL_11:.*]] = hlfir.as_expr %[[VAL_2]] move %{{.*}} : (!fir.ref>, i1) -> !hlfir.expr> +! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_4_DECL]]#0 : !hlfir.expr>, !fir.ref> +! CHECK: hlfir.destroy %[[VAL_11]] : !hlfir.expr> ! CHECK: return ! CHECK: } subroutine test1(x, c) diff --git a/flang/test/Lower/Intrinsics/acospi.f90 b/flang/test/Lower/Intrinsics/acospi.f90 index 38c547fd5dd13..75f50d0140e32 100644 --- a/flang/test/Lower/Intrinsics/acospi.f90 +++ b/flang/test/Lower/Intrinsics/acospi.f90 @@ -1,16 +1,15 @@ ! REQUIRES: flang-supports-f128-math -! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST" -! RUN: bbc --math-runtime=precise -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-PRECISE" -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST" +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST" +! RUN: %flang_fc1 -emit-hlfir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-PRECISE" function test_real4(x) real :: x, test_real4 test_real4 = acospi(x) end function -! CHECK-LABEL: @_QPtest_real4 +! CHECK-LABEL: func.func @_QPtest_real4( ! CHECK-PRECISE: %[[acos:.*]] = fir.call @acosf({{%[A-Za-z0-9._]+}}) fastmath : (f32) -> f32 -! CHECK-FAST: %[[acos:.*]] = math.acos %{{.*}} : f32 +! CHECK-FAST: %[[acos:.*]] = math.acos %{{.*}} fastmath : f32 ! CHECK: %[[inv_pi:.*]] = arith.constant 0.318309873 : f32 ! CHECK: %{{.*}} = arith.mulf %[[acos]], %[[inv_pi]] fastmath : f32 @@ -19,9 +18,9 @@ function test_real8(x) test_real8 = acospi(x) end function -! CHECK-LABEL: @_QPtest_real8 +! CHECK-LABEL: func.func @_QPtest_real8( ! CHECK-PRECISE: %[[acos:.*]] = fir.call @acos({{%[A-Za-z0-9._]+}}) fastmath : (f64) -> f64 -! CHECK-FAST: %[[acos:.*]] = math.acos %{{.*}} : f64 +! CHECK-FAST: %[[acos:.*]] = math.acos %{{.*}} fastmath : f64 ! CHECK: %[[inv_pi:.*]] = arith.constant 0.31830988618379069 : f64 ! CHECK: %{{.*}} = arith.mulf %[[acos]], %[[inv_pi]] fastmath : f64 @@ -30,7 +29,7 @@ function test_real16(x) test_real16 = acospi(x) end function -! CHECK-LABEL: @_QPtest_real16 +! CHECK-LABEL: func.func @_QPtest_real16( ! CHECK: %[[acos:.*]] = fir.call @_FortranAAcosF128({{.*}}) fastmath : (f128) -> f128 ! CHECK: %[[inv_pi:.*]] = arith.constant 0.3183098861837906715377675267450{{.*}} : f128 ! CHECK: %{{.*}} = arith.mulf %[[acos]], %[[inv_pi]] fastmath : f128 diff --git a/flang/test/Lower/Intrinsics/adjustl.f90 b/flang/test/Lower/Intrinsics/adjustl.f90 index b66a8409c083d..fc0fc757b70bc 100644 --- a/flang/test/Lower/Intrinsics/adjustl.f90 +++ b/flang/test/Lower/Intrinsics/adjustl.f90 @@ -1,16 +1,17 @@ -! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s ! CHECK-LABEL: adjustl_test subroutine adjustl_test character(len=12) :: adjust_str = ' 0123456789' - ! CHECK: %[[strBox:.*]] = fir.alloca !fir.box>> - ! CHECK: %[[addr0:.*]] = fir.address_of(@_QFadjustl{{.*}}) : !fir.ref> - ! CHECK: %[[eBox:.*]] = fir.embox %[[addr0]] : (!fir.ref>) -> !fir.box> - ! CHECK: %[[r0:.*]] = fir.zero_bits !fir.heap> - ! CHECK: %[[r1:.*]] = fir.embox %[[r0]] typeparams %{{.*}} : (!fir.heap>, index) -> !fir.box>> - ! CHECK: fir.store %[[r1]] to %[[strBox]] : !fir.ref>>> + ! CHECK: %[[strBox:.*]] = fir.alloca !fir.box>> + ! CHECK: %[[addr:.*]] = fir.address_of(@_QFadjustl_testEadjust_str) : !fir.ref> + ! CHECK: %[[str_decl:.*]]:2 = hlfir.declare %[[addr]] + ! CHECK: %[[eBox:.*]] = fir.embox %[[str_decl]]#0 : (!fir.ref>) -> !fir.box> + ! CHECK: %[[r0:.*]] = fir.zero_bits !fir.heap> + ! CHECK: %[[r1:.*]] = fir.embox %[[r0]] : (!fir.heap>) -> !fir.box>> + ! CHECK: fir.store %[[r1]] to %[[strBox]] : !fir.ref>>> ! CHECK: %[[r2:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref> - ! CHECK: %[[r3:.*]] = fir.convert %[[strBox]] : (!fir.ref>>>) -> !fir.ref> + ! CHECK: %[[r3:.*]] = fir.convert %[[strBox]] : (!fir.ref>>>) -> !fir.ref> ! CHECK: %[[r4:.*]] = fir.convert %[[eBox]] : (!fir.box>) -> !fir.box ! CHECK: %[[r5:.*]] = fir.convert %[[r2]] : (!fir.ref>) -> !fir.ref ! CHECK: fir.call @_FortranAAdjustl(%[[r3]], %[[r4]], %[[r5]], %{{.*}}) {{.*}}: (!fir.ref>, !fir.box, !fir.ref, i32) -> () diff --git a/flang/test/Lower/intentout-deallocate.f90 b/flang/test/Lower/intentout-deallocate.f90 index 23289def29157..fc49fa83523b9 100644 --- a/flang/test/Lower/intentout-deallocate.f90 +++ b/flang/test/Lower/intentout-deallocate.f90 @@ -1,6 +1,5 @@ ! Test correct deallocation of intent(out) allocatables. -! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes=CHECK,FIR -! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s --check-prefixes=CHECK,HLFIR +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s module mod1 type, bind(c) :: t1 @@ -49,8 +48,8 @@ subroutine sub1(a) ! Check inline deallocation of allocatable intent(out) on the callee side. ! CHECK-LABEL: func.func @_QMmod1Psub1( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub1Ea" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub1Ea" ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 @@ -75,40 +74,23 @@ subroutine sub2() ! Check inlined deallocation of allocatble intent(out) on the caller side for BIND(C). -! FIR-LABEL: func.func @_QMmod1Psub2() -! FIR: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QMmod1Fsub2Ea"} -! FIR: %[[BOX_ALLOC:.*]] = fir.alloca !fir.heap> {uniq_name = "_QMmod1Fsub2Ea.addr"} -! FIR: %[[BOX_ADDR:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> -! FIR: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 -! FIR: %[[C0:.*]] = arith.constant 0 : i64 -! FIR: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 -! FIR: fir.if %[[IS_ALLOCATED]] { -! FIR: %[[LOAD:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> -! FIR: fir.freemem %[[LOAD]] : !fir.heap> -! FIR: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! FIR: fir.store %[[ZERO]] to %[[BOX_ALLOC]] : !fir.ref>> -! FIR: } -! FIR: %[[LOAD:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> -! FIR: %{{.*}} = fir.embox %[[LOAD]](%{{.*}}) : (!fir.heap>, !fir.shapeshift< -! FIR: fir.call @sub3(%[[BOX]]) {{.*}}: (!fir.ref>>>) -> () - -! HLFIR-LABEL: func.func @_QMmod1Psub2( -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub2Ea" -! HLFIR: %[[BOX:.*]] = fir.load %[[ARG0]]#0 : !fir.ref>>> -! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> -! HLFIR: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 -! HLFIR: %[[C0:.*]] = arith.constant 0 : i64 -! HLFIR: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 -! HLFIR: fir.if %[[IS_ALLOCATED]] { -! HLFIR: %[[BOX:.*]] = fir.load %[[ARG0]]#0 : !fir.ref>>> -! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> -! HLFIR: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! HLFIR: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! HLFIR: %[[C0:.*]] = arith.constant 0 : index -! HLFIR: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! HLFIR: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! HLFIR: fir.store %[[EMBOX]] to %[[ARG0]]#0 : !fir.ref>>> -! HLFIR: fir.call @sub3(%[[ARG0]]#0) {{.*}}: (!fir.ref>>>) -> () +! CHECK-LABEL: func.func @_QMmod1Psub2( +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub2Ea" +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]#0 : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]#0 : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]]#0 : !fir.ref>>> +! CHECK: fir.call @sub3(%[[ARG0]]#0) {{.*}}: (!fir.ref>>>) -> () subroutine sub4() type(t1), allocatable :: t @@ -123,8 +105,8 @@ subroutine sub5(t) ! on the caller side. ! CHECK-LABEL: func.func @_QMmod1Psub4() -! FIR: %[[BOX:.*]] = fir.alloca !fir.box]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub4Et"} -! HLFIR: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub4Et" +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub4Et"} +! CHECK: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub4Et" ! CHECK-NOT: fir.call @_FortranAAllocatableDeallocate ! CHECK: fir.call @_QMmod1Psub5(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref]?}}>>>>) -> () @@ -132,8 +114,8 @@ subroutine sub5(t) ! is done with a runtime call. ! CHECK-LABEL: func.func @_QMmod1Psub5( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref]?}}>>>> {fir.bindc_name = "t"}) -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub5Et" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref]?}}>>>> {fir.bindc_name = "t"}) +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub5Et" ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref]?}}>>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box]?}}>>>) -> !fir.heap]?}}>> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap]?}}>>) -> i64 @@ -152,8 +134,8 @@ subroutine sub6() ! Deallocation is done with a runtime call. ! CHECK-LABEL: func.func @_QMmod1Psub6() -! FIR: %[[BOX:.*]] = fir.alloca !fir.box]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub6Et"} -! HLFIR: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub6Et" +! CHECK: %[[BOX:.*]] = fir.alloca !fir.box]?}}>>> {bindc_name = "t", uniq_name = "_QMmod1Fsub6Et"} +! CHECK: %[[BOX:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub6Et" ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOX]]{{[#0]*}} : (!fir.ref]?}}>>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocate(%[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: fir.call @sub7(%[[BOX]]{{[#0]*}}) {{.*}}: (!fir.ref]?}}>>>>) -> () @@ -178,8 +160,8 @@ subroutine sub9(a) ! Check inline deallocation of optional allocatable intent(out) on the callee side. ! CHECK-LABEL: func.func @_QMmod1Psub9( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a", fir.optional}) -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub9Ea" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a", fir.optional}) +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub9Ea" ! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0]]{{[#0]*}} : (!fir.ref>>>) -> i1 ! CHECK: fir.if %[[IS_PRESENT]] { ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> @@ -206,8 +188,8 @@ subroutine sub10(a) end subroutine ! CHECK-LABEL: func.func @_QMmod1Psub10( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub10Ea" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub10Ea" ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 @@ -233,8 +215,8 @@ subroutine sub12(a) end subroutine ! CHECK-LABEL: func.func @_QMmod1Psub12( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea" ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 @@ -252,8 +234,8 @@ subroutine sub12(a) ! CHECK: } ! CHECK-LABEL: func.func @_QMmod1Psub13( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub12Ea" ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 @@ -276,8 +258,8 @@ subroutine sub14(p) end subroutine ! CHECK-LABEL: func.func @_QMmod1Psub14( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p"}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub14Ep" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p"}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub14Ep" ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.class>>) -> !fir.heap> ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 @@ -295,8 +277,8 @@ subroutine sub15(p) end subroutine ! CHECK-LABEL: func.func @_QMmod1Psub15( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>> {fir.bindc_name = "p"}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub15Ep" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>> {fir.bindc_name = "p"}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub15Ep" ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.class>) -> !fir.heap ! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap) -> i64 @@ -313,8 +295,8 @@ subroutine sub16(p) end subroutine ! CHECK-LABEL: func.func @_QMmod1Psub16( -! FIR-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p", fir.optional}) { -! HLFIR: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub16Ep" +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "p", fir.optional}) { +! CHECK: %[[ARG0:.*]]:2 = hlfir.declare {{.*}}"_QMmod1Fsub16Ep" ! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0]]{{[#0]*}} : (!fir.ref>>>) -> i1 ! CHECK: fir.if %[[IS_PRESENT]] { ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]]{{[#0]*}} : !fir.ref>>> From bad56dbb23853e1413d8df13a26b6a1dc02907a1 Mon Sep 17 00:00:00 2001 From: Kseniya Tikhomirova Date: Fri, 27 Feb 2026 18:43:34 +0100 Subject: [PATCH 10/58] [libsycl] Add sycl::context stub (#182826) Part 1 of changes needed for USM alloc/dealloc impl. This is part of the SYCL support upstreaming effort. The relevant RFCs can be found here: https://discourse.llvm.org/t/rfc-add-full-support-for-the-sycl-programming-model/74080 https://discourse.llvm.org/t/rfc-sycl-runtime-upstreaming/74479 --------- Signed-off-by: Tikhomirova, Kseniya --- libsycl/docs/index.rst | 2 +- libsycl/include/sycl/__impl/context.hpp | 93 ++++++++++++++++++++ libsycl/include/sycl/__impl/device.hpp | 2 +- libsycl/include/sycl/sycl.hpp | 1 + libsycl/src/CMakeLists.txt | 2 + libsycl/src/context.cpp | 35 ++++++++ libsycl/src/detail/context_impl.cpp | 27 ++++++ libsycl/src/detail/context_impl.hpp | 70 +++++++++++++++ libsycl/src/detail/device_impl.cpp | 6 +- libsycl/src/detail/device_impl.hpp | 4 +- libsycl/src/detail/offload/offload_utils.hpp | 4 +- libsycl/src/detail/platform_impl.cpp | 9 ++ libsycl/src/detail/platform_impl.hpp | 17 +++- libsycl/src/device.cpp | 2 - libsycl/src/platform.cpp | 1 + 15 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 libsycl/include/sycl/__impl/context.hpp create mode 100644 libsycl/src/context.cpp create mode 100644 libsycl/src/detail/context_impl.cpp create mode 100644 libsycl/src/detail/context_impl.hpp diff --git a/libsycl/docs/index.rst b/libsycl/docs/index.rst index 03e083227ace4..01bfb19b3d432 100644 --- a/libsycl/docs/index.rst +++ b/libsycl/docs/index.rst @@ -105,4 +105,4 @@ TODO for added SYCL classes * ``has_extension``: deprecated API, to implement on RT level with ``device::has`` * device selection: to add compatibility with old SYCL 1.2.1 device selectors, still part of SYCL 2020 specification - +* ``context``: to implement get_info, properties & public constructors once context support is added to liboffload diff --git a/libsycl/include/sycl/__impl/context.hpp b/libsycl/include/sycl/__impl/context.hpp new file mode 100644 index 0000000000000..3acc91fad9647 --- /dev/null +++ b/libsycl/include/sycl/__impl/context.hpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the SYCL context class, which +/// represents the runtime data structures and state required by a SYCL backend +/// API to interact with a group of devices associated with a platform. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_CONTEXT_HPP +#define _LIBSYCL___IMPL_CONTEXT_HPP + +#include +#include + +#include +#include + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +class context; +class device; +class platform; + +namespace detail { +class ContextImpl; +template +using is_context_info_desc_t = typename is_info_desc::return_type; +} // namespace detail + +// SYCL 2020 4.6.3. Context class +class _LIBSYCL_EXPORT context { +public: + context(const context &rhs) = default; + + context(context &&rhs) = default; + + context &operator=(const context &rhs) = default; + + context &operator=(context &&rhs) = default; + + friend bool operator==(const context &lhs, const context &rhs) { + return lhs.impl == rhs.impl; + } + + friend bool operator!=(const context &lhs, const context &rhs) { + return !(lhs == rhs); + } + + /// \return the backend associated with this context. + backend get_backend() const noexcept; + + /// \return the platform associated with this SYCL context. + platform get_platform() const; + + /// \return a vector of valid SYCL devices associated with this SYCL context. + std::vector get_devices() const; + + /// Queries this SYCL context for information. + /// + /// The return type depends on information being queried. + template + detail::is_context_info_desc_t get_info() const; + + /// Queries this SYCL context for SYCL backend-specific information. + /// + /// The return type depends on information being queried. + template + typename Param::return_type get_backend_info() const; + +private: + context(const std::shared_ptr &Impl) : impl(Impl) {} + std::shared_ptr impl; + + friend sycl::detail::ImplUtils; +}; // class context + +_LIBSYCL_END_NAMESPACE_SYCL + +template <> +struct std::hash : public sycl::detail::HashBase { +}; + +#endif // _LIBSYCL___IMPL_CONTEXT_HPP diff --git a/libsycl/include/sycl/__impl/device.hpp b/libsycl/include/sycl/__impl/device.hpp index 55b624f8fcbd5..fa4c888d66582 100644 --- a/libsycl/include/sycl/__impl/device.hpp +++ b/libsycl/include/sycl/__impl/device.hpp @@ -52,7 +52,7 @@ class _LIBSYCL_EXPORT device { /// Constructs a SYCL device instance using the default device (device chosen /// by default device selector). - device(); + device() : device(default_selector_v) {} /// Constructs a SYCL device instance using the device /// identified by the provided device selector. diff --git a/libsycl/include/sycl/sycl.hpp b/libsycl/include/sycl/sycl.hpp index 3e7f81092256c..5823f29268567 100644 --- a/libsycl/include/sycl/sycl.hpp +++ b/libsycl/include/sycl/sycl.hpp @@ -14,6 +14,7 @@ #ifndef _LIBSYCL_SYCL_HPP #define _LIBSYCL_SYCL_HPP +#include #include #include #include diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt index 0a83f2ef36443..fa3bf81e17d2a 100644 --- a/libsycl/src/CMakeLists.txt +++ b/libsycl/src/CMakeLists.txt @@ -81,11 +81,13 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) endfunction(add_sycl_rt_library) set(LIBSYCL_SOURCES + "context.cpp" "exception.cpp" "exception_list.cpp" "device.cpp" "device_selector.cpp" "platform.cpp" + "detail/context_impl.cpp" "detail/device_impl.cpp" "detail/global_objects.cpp" "detail/platform_impl.cpp" diff --git a/libsycl/src/context.cpp b/libsycl/src/context.cpp new file mode 100644 index 0000000000000..3241d6fd47b67 --- /dev/null +++ b/libsycl/src/context.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +#include +#include + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +backend context::get_backend() const noexcept { return impl->getBackend(); } + +platform context::get_platform() const { + return detail::createSyclObjFromImpl(impl->getPlatformImpl()); +} + +std::vector context::get_devices() const { + std::vector Devices; + + impl->iterateDevices([&Devices](detail::DeviceImpl *DevImpl) { + assert(DevImpl && "Device impl can't be nullptr"); + Devices.push_back(detail::createSyclObjFromImpl(*DevImpl)); + }); + + return Devices; +} + +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/context_impl.cpp b/libsycl/src/detail/context_impl.cpp new file mode 100644 index 0000000000000..264716fbdfad4 --- /dev/null +++ b/libsycl/src/detail/context_impl.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +void ContextImpl::iterateDevices( + const std::function &callback) const { + // TODO: Intentionally don't store devices in context now. This class should + // be reimplemented once liboffload adds context support. Treat context as + // default context that is associated with all devices in the platform. + return MPlatform.iterateDevices(info::device_type::all, callback); +} + +backend ContextImpl::getBackend() const { return MPlatform.getBackend(); } + +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/context_impl.hpp b/libsycl/src/detail/context_impl.hpp new file mode 100644 index 0000000000000..30b3f50f17645 --- /dev/null +++ b/libsycl/src/detail/context_impl.hpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_CONTEXT_IMPL +#define _LIBSYCL_CONTEXT_IMPL + +#include +#include + +#include + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL +namespace detail { + +class PlatformImpl; +class DeviceImpl; + +// TODO: Presence of context object is essential for many APIs. Current +// implementation of this class is a way to support them in case of absence of +// context support in liboffload. For backends where context exists and +// participates in operations, liboffload plugins create and use default context +// that represents all devices in that platform. Duplicating this logic here. +/// Context represents the runtime data structures and state required by a SYCL +/// backend API to interact with a group of devices associated with a platform. +class ContextImpl : public std::enable_shared_from_this { + struct Private { + explicit Private() = default; + }; + +public: + /// Constructs a ContextImpl using a platform. + /// + /// Newly created instance represents all devices in platform. + /// + /// \param Platform is a platform to associate this context with. + ContextImpl(PlatformImpl &Platform, Private) : MPlatform(Platform) {} + + /// Constructs a ContextImpl with a provided arguments. Variadic helper. + /// Restrics ways of ContextImpl creation. + template + static std::shared_ptr create(Ts &&...args) { + return std::make_shared(std::forward(args)..., Private{}); + } + + /// \return the platform this context is associated with. + PlatformImpl &getPlatformImpl() const { return MPlatform; } + + /// Calls "callback" with every device associated + /// with this context. + void iterateDevices(const std::function &callback) const; + + /// \return backend of the platform this context is associated with. + backend getBackend() const; + +private: + PlatformImpl &MPlatform; +}; + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_CONTEXT_IMPL diff --git a/libsycl/src/detail/device_impl.cpp b/libsycl/src/detail/device_impl.cpp index de702cc4b7839..d12f97d0db864 100644 --- a/libsycl/src/detail/device_impl.cpp +++ b/libsycl/src/detail/device_impl.cpp @@ -22,9 +22,7 @@ bool DeviceImpl::has(aspect Aspect) const { case (aspect::accelerator): return isAccelerator(); case (aspect::custom): - return false; case (aspect::emulated): - return false; case (aspect::host_debuggable): return false; default: @@ -49,7 +47,9 @@ bool DeviceImpl::isAccelerator() const { return getDeviceType() == info::device_type::accelerator; } -backend DeviceImpl::getBackend() const { return MPlatform.getBackend(); } +backend DeviceImpl::getBackend() const noexcept { + return MPlatform.getBackend(); +} } // namespace detail _LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/device_impl.hpp b/libsycl/src/detail/device_impl.hpp index 5fd0893c99125..c83b767aad02f 100644 --- a/libsycl/src/detail/device_impl.hpp +++ b/libsycl/src/detail/device_impl.hpp @@ -65,7 +65,7 @@ class DeviceImpl { /// Returns the backend associated with this device. /// /// \return the sycl::backend associated with this device. - backend getBackend() const; + backend getBackend() const noexcept; /// Returns the implementation class object of platform associated with this /// device. @@ -115,6 +115,8 @@ class DeviceImpl { static_assert(false && "Info descriptor is not properly supported"); } + ol_device_handle_t getOLHandle() { return MOffloadDevice; } + private: ol_device_handle_t MOffloadDevice = {}; PlatformImpl &MPlatform; diff --git a/libsycl/src/detail/offload/offload_utils.hpp b/libsycl/src/detail/offload/offload_utils.hpp index f32326fb87fc9..e849ee137337f 100644 --- a/libsycl/src/detail/offload/offload_utils.hpp +++ b/libsycl/src/detail/offload/offload_utils.hpp @@ -37,6 +37,8 @@ inline std::string formatCodeString(ol_result_t Result) { std::string(stringifyErrorCode(Result->Code)) + ") " + Result->Details; } +inline bool isFailed(const ol_result_t &Result) { return Result != OL_SUCCESS; } + /// Checks liboffload API call result. /// /// Used after calling the API without check. @@ -48,7 +50,7 @@ inline std::string formatCodeString(ol_result_t Result) { /// \throw sycl::runtime_exception if the call was not successful. template void checkAndThrow(ol_result_t Result) { - if (Result != OL_SUCCESS) { + if (isFailed(Result)) { throw sycl::exception(sycl::make_error_code(errc), detail::formatCodeString(Result)); } diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp index d96ee4af311a6..69f5d2bf0434a 100644 --- a/libsycl/src/detail/platform_impl.cpp +++ b/libsycl/src/detail/platform_impl.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,8 @@ PlatformImpl::PlatformImpl(ol_platform_handle_t Platform, size_t PlatformIndex, MRootDevices.emplace_back(std::make_unique( Device, *this, DeviceImpl::PrivateTag{})); }); + + MDefaultContext = ContextImpl::create(*this); } const std::vector &PlatformImpl::getRootDevices() const { @@ -121,5 +124,11 @@ void PlatformImpl::iterateDevices( } } +ContextImpl &PlatformImpl::getDefaultContext() { + assert(MDefaultContext && + "Default context for platform must be created in platform ctor"); + return *MDefaultContext.get(); +} + } // namespace detail _LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp index e23ce6a492281..2ee0b0c4f5449 100644 --- a/libsycl/src/detail/platform_impl.hpp +++ b/libsycl/src/detail/platform_impl.hpp @@ -29,6 +29,7 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL namespace detail { class DeviceImpl; +class ContextImpl; using PlatformImplUPtr = std::unique_ptr; using DeviceImplUPtr = std::unique_ptr; @@ -52,8 +53,6 @@ class PlatformImpl { ~PlatformImpl() = default; - /// Returns the backend associated with this platform. - /// /// \returns sycl::backend associated with this platform. backend getBackend() const noexcept { return MBackend; } @@ -121,15 +120,25 @@ class PlatformImpl { void iterateDevices(info::device_type DeviceType, std::function callback) const; + // TODO: liboffload doesn't support context now, l0 plugin creates default + // context for all devices on its level. This method should be removed or + // reimplemented once native context support is added to liboffload. + /// \return the default context that represents all devices in platform. + ContextImpl &getDefaultContext(); + private: + /// \return reference to collection of root devices for platform const std::vector &getRootDevices() const; - ol_platform_handle_t MOffloadPlatform{}; - size_t MOffloadPlatformIndex{}; + const ol_platform_handle_t MOffloadPlatform{}; + const size_t MOffloadPlatformIndex{}; + ol_platform_backend_t MOffloadBackend{OL_PLATFORM_BACKEND_UNKNOWN}; backend MBackend{}; std::vector MRootDevices; + + std::shared_ptr MDefaultContext; }; } // namespace detail diff --git a/libsycl/src/device.cpp b/libsycl/src/device.cpp index db61d2ff3a22e..eca7beb49cb4f 100644 --- a/libsycl/src/device.cpp +++ b/libsycl/src/device.cpp @@ -15,8 +15,6 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL -device::device() : device(default_selector_v) {} - bool device::is_cpu() const { return impl->isCPU(); } bool device::is_gpu() const { return impl->isGPU(); } diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp index c04c0a6281774..655c984fcadf7 100644 --- a/libsycl/src/platform.cpp +++ b/libsycl/src/platform.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include #include #include From 7f0a343a8ec48b41e3866cdbabfc8740985a44f3 Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Sat, 28 Feb 2026 01:45:52 +0800 Subject: [PATCH 11/58] [flang] Implement -grecord-command-line for Flang (#181686) Enable Flang to match Clang behavior for command-line recording in DWARF producer strings when using -grecord-command-line. Signed-off-by: Yangyu Chen --- clang/include/clang/Options/Options.td | 12 +++++++----- flang/include/flang/Frontend/CodeGenOptions.h | 5 +++++ flang/include/flang/Optimizer/Passes/Pipelines.h | 7 +++++-- flang/include/flang/Optimizer/Transforms/Passes.td | 5 ++++- flang/include/flang/Tools/CrossToolHelpers.h | 2 ++ flang/lib/Frontend/CompilerInvocation.cpp | 5 +++++ flang/lib/Optimizer/Passes/Pipelines.cpp | 12 ++++++++---- flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 8 ++++++-- flang/test/Driver/grecord-command-line.f90 | 14 ++++++++++++++ flang/test/Transforms/debug-dwarf-debug-flags.fir | 14 ++++++++++++++ 10 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 flang/test/Driver/grecord-command-line.f90 create mode 100644 flang/test/Transforms/debug-dwarf-debug-flags.fir diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index f024dc4055e22..4dbfe0eb6f1af 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -5005,9 +5005,11 @@ def gxcoff : Joined<["-"], "gxcoff">, Group, Flags<[Unsupported]>; def gvms : Joined<["-"], "gvms">, Group, Flags<[Unsupported]>; def gtoggle : Flag<["-"], "gtoggle">, Group, Flags<[Unsupported]>; def grecord_command_line : Flag<["-"], "grecord-command-line">, - Group; + Group, + Visibility<[ClangOption, FlangOption]>; def gno_record_command_line : Flag<["-"], "gno-record-command-line">, - Group; + Group, + Visibility<[ClangOption, FlangOption]>; def : Flag<["-"], "grecord-gcc-switches">, Alias; def : Flag<["-"], "gno-record-gcc-switches">, Alias; defm strict_dwarf : BoolOption<"g", "strict-dwarf", @@ -7951,6 +7953,9 @@ def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; def record_command_line : Separate<["-"], "record-command-line">, HelpText<"The string to embed in the .LLVM.command.line section.">, MarshallingInfoString>; +def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, + HelpText<"The string to embed in the Dwarf debug flags record.">, + MarshallingInfoString>; def dwarf_version_EQ : Joined<["-"], "dwarf-version=">, MarshallingInfoInt>; @@ -7972,9 +7977,6 @@ def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">, Values<"gdb,lldb,sce,dbx">, NormalizedValuesScope<"llvm::DebuggerKind">, NormalizedValues<["GDB", "LLDB", "SCE", "DBX"]>, MarshallingInfoEnum, "Default">; -def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, - HelpText<"The string to embed in the Dwarf debug flags record.">, - MarshallingInfoString>; def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">, HelpText<"DWARF debug sections compression type">, Values<"none,zlib,zstd">, NormalizedValuesScope<"llvm::DebugCompressionType">, NormalizedValues<["None", "Zlib", "Zstd"]>, diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index 3dca169d43b39..5a141e3c0a87d 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -73,6 +73,11 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The string containing the commandline for the llvm.commandline metadata. std::optional RecordCommandLine; + /// The value from -dwarf-debug-flags to append to DW_AT_producer. + /// This is typically a reconstructed user command line (e.g. from + /// -grecord-command-line) and may contain multiple space-separated flags. + std::string DwarfDebugFlags; + /// The name of the file to which the backend should save YAML optimization /// records. std::string OptRecordFile; diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h index 1a7ff4ff3dfa2..8f2ff5f82299d 100644 --- a/flang/include/flang/Optimizer/Passes/Pipelines.h +++ b/flang/include/flang/Optimizer/Passes/Pipelines.h @@ -103,7 +103,9 @@ void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm); void addDebugInfoPass(mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel, llvm::OptimizationLevel optLevel, - llvm::StringRef inputFilename, int32_t dwarfVersion); + llvm::StringRef inputFilename, int32_t dwarfVersion, + llvm::StringRef splitDwarfFile, + llvm::StringRef dwarfDebugFlags); /// Create FIRToLLVMPassOptions from pipeline configuration. FIRToLLVMPassOptions @@ -164,7 +166,8 @@ void createDebugPasses(mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel, llvm::OptimizationLevel OptLevel, llvm::StringRef inputFilename, int32_t dwarfVersion, - llvm::StringRef splitDwarfFile); + llvm::StringRef splitDwarfFile, + llvm::StringRef dwarfDebugFlags); void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index d812e271b158d..bdee252d14c72 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -260,7 +260,10 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> { "dwarf version">, Option<"splitDwarfFile", "split-dwarf-file", "std::string", /*default=*/"std::string{}", - "Name of the split dwarf file"> + "Name of the split dwarf file">, + Option<"dwarfDebugFlags", "dwarf-debug-flags", + "std::string", /*default=*/"std::string{}", + "Command-line flags to append to DWARF producer"> ]; } diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index 44fb252d2b366..f29fc8ef0ea56 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -110,6 +110,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { } DwarfVersion = opts.DwarfVersion; SplitDwarfFile = opts.SplitDwarfFile; + DwarfDebugFlags = opts.DwarfDebugFlags; } llvm::OptimizationLevel OptLevel; ///< optimisation level @@ -148,6 +149,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { CX_Full; ///< Method for calculating complex number division int32_t DwarfVersion = 0; ///< Version of DWARF debug info to generate std::string SplitDwarfFile = ""; ///< File name for the split debug info + std::string DwarfDebugFlags = ""; ///< Debug flags to append to DWARF producer }; struct OffloadModuleOpts { diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index fc4975f9592eb..72b766e52ab3b 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -165,6 +165,11 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, args.getLastArg(clang::options::OPT_split_dwarf_output)) opts.SplitDwarfOutput = a->getValue(); } + + if (const llvm::opt::Arg *arg = + args.getLastArg(clang::options::OPT_dwarf_debug_flags)) + opts.DwarfDebugFlags = arg->getValue(); + return true; } diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 5927fff960270..bb1ad84523c82 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -97,13 +97,15 @@ void addDebugInfoPass(mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel, llvm::OptimizationLevel optLevel, llvm::StringRef inputFilename, int32_t dwarfVersion, - llvm::StringRef splitDwarfFile) { + llvm::StringRef splitDwarfFile, + llvm::StringRef dwarfDebugFlags) { fir::AddDebugInfoOptions options; options.debugLevel = getEmissionKind(debugLevel); options.isOptimized = optLevel != llvm::OptimizationLevel::O0; options.inputFilename = inputFilename; options.dwarfVersion = dwarfVersion; options.splitDwarfFile = splitDwarfFile; + options.dwarfDebugFlags = dwarfDebugFlags; addPassConditionally(pm, disableDebugInfo, [&]() { return fir::createAddDebugInfoPass(options); }); } @@ -361,10 +363,11 @@ void createDebugPasses(mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel, llvm::OptimizationLevel OptLevel, llvm::StringRef inputFilename, int32_t dwarfVersion, - llvm::StringRef splitDwarfFile) { + llvm::StringRef splitDwarfFile, + llvm::StringRef dwarfDebugFlags) { if (debugLevel != llvm::codegenoptions::NoDebugInfo) addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename, dwarfVersion, - splitDwarfFile); + splitDwarfFile, dwarfDebugFlags); } void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, @@ -383,7 +386,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo)); fir::addExternalNameConversionPass(pm, config.Underscoring); fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename, - config.DwarfVersion, config.SplitDwarfFile); + config.DwarfVersion, config.SplitDwarfFile, + config.DwarfDebugFlags); fir::addTargetRewritePass(pm); fir::addCompilerGeneratedNamesConversionPass(pm); diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 63698fdb88909..c42f5a29ecd62 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -927,8 +927,12 @@ void AddDebugInfoPass::runOnOperation() { mlir::LLVM::DIFileAttr fileAttr = mlir::LLVM::DIFileAttr::get(context, fileName, filePath); - mlir::StringAttr producer = - mlir::StringAttr::get(context, Fortran::common::getFlangFullVersion()); + // Match Clang style by starting with the full compiler version and + // appending -dwarf-debug-flags content when provided. + std::string producerString = Fortran::common::getFlangFullVersion(); + if (!dwarfDebugFlags.empty()) + producerString += " " + dwarfDebugFlags; + mlir::StringAttr producer = mlir::StringAttr::get(context, producerString); mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get( mlir::DistinctAttr::create(mlir::UnitAttr::get(context)), llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, diff --git a/flang/test/Driver/grecord-command-line.f90 b/flang/test/Driver/grecord-command-line.f90 new file mode 100644 index 0000000000000..269381e464e7d --- /dev/null +++ b/flang/test/Driver/grecord-command-line.f90 @@ -0,0 +1,14 @@ +! This checks that -grecord-command-line is forwarded by the flang driver to +! an FC1 -dwarf-debug-flags argument and that -gno-record-command-line +! disables it, matching clang behavior. +! +! RUN: %flang -### -grecord-command-line %s 2>&1 | FileCheck --check-prefix=GRECORD %s +! RUN: %flang -### -gno-record-command-line %s 2>&1 | FileCheck --check-prefix=GNO_RECORD %s +! RUN: %flang -### -grecord-command-line -gno-record-command-line %s 2>&1 | FileCheck --check-prefix=GNO_RECORD %s +! +! GRECORD: "-dwarf-debug-flags" +! +! GNO_RECORD-NOT: "-dwarf-debug-flags" + +program p +end program p diff --git a/flang/test/Transforms/debug-dwarf-debug-flags.fir b/flang/test/Transforms/debug-dwarf-debug-flags.fir new file mode 100644 index 0000000000000..78f3989589e51 --- /dev/null +++ b/flang/test/Transforms/debug-dwarf-debug-flags.fir @@ -0,0 +1,14 @@ +// Test the dwarf-debug-flags option will show up in the generated debug info. +// RUN: fir-opt --add-debug-info="debug-level=Full dwarf-debug-flags=\"-grecord-command-line -O2\"" \ +// RUN: --mlir-print-debuginfo %s | FileCheck --check-prefix=CHECK-FLAGS %s + +module { + func.func @_QPs() { + return loc(#loc_s) + } loc(#loc_s) +} loc(#loc_module) +#loc_module = loc("simple.f90":1:1) +#loc_s = loc("simple.f90":2:1) + +// CHECK-FLAGS: #llvm.di_compile_unit< +// CHECK-FLAGS: producer = "{{.*}} -grecord-command-line -O2" From dc26edd9b6602857b67f35c8d2f6fe4ed13c8137 Mon Sep 17 00:00:00 2001 From: Amit Kumar Pandey Date: Fri, 27 Feb 2026 23:19:37 +0530 Subject: [PATCH 12/58] [ASan] Enable Internalization for 'asanrtl.bc' in Driver (#182825) Just like other bitcode libs such as ockl.bc ocml.bc, link asanrtl.bc with '-mlink-builtin-bitcode' in the driver when GPU ASan is enabled. --- clang/lib/Driver/ToolChains/AMDGPU.cpp | 2 +- .../Driver/amdgpu-openmp-sanitize-options.c | 2 +- clang/test/Driver/hip-sanitize-options.hip | 24 +++++++++---------- clang/test/Driver/rocm-device-libs.cl | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 95f14640937ea..377e851be6e26 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -1035,7 +1035,7 @@ RocmInstallationDetector::getCommonBitcodeLibs( }; auto AddSanBCLibs = [&]() { if (Pref.GPUSan) - AddBCLib(getAsanRTLPath(), false); + AddBCLib(getAsanRTLPath()); }; AddSanBCLibs(); diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c b/clang/test/Driver/amdgpu-openmp-sanitize-options.c index fd7d11803249c..8fb53121e92b4 100644 --- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c +++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c @@ -104,7 +104,7 @@ // HOSTSANCOMBINATION: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address,fuzzer,fuzzer-no-link".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}} // HOSTSANCOMBINATION2: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address,fuzzer,fuzzer-no-link,leak".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}} -// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-bitcode-file" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} +// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-builtin-bitcode" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} // NOGPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-target-cpu" "(gfx908|gfx900)".* "-fopenmp".* "-x" "c".*}} // SAN: {{"[^"]*llvm-offload-binary[^"]*" "-o".* "--image=file=.*.bc,triple=amdgcn-amd-amdhsa,arch=(gfx908|gfx1250|gfx1251)(:xnack\-|:xnack\+)?,kind=openmp(,feature=(\-xnack|\+xnack))?"}} diff --git a/clang/test/Driver/hip-sanitize-options.hip b/clang/test/Driver/hip-sanitize-options.hip index 4deffc32430fb..1e69d38f8026f 100644 --- a/clang/test/Driver/hip-sanitize-options.hip +++ b/clang/test/Driver/hip-sanitize-options.hip @@ -98,14 +98,14 @@ // RUN: | FileCheck -check-prefixes=ERRSANCOV %s // CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address"}} -// CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-bitcode-file" ".*asanrtl.bc"}} +// CHECK-NOT: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-mlink-builtin-bitcode" ".*asanrtl.bc"}} // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}} // CHECK: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} -// NORDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* .* "-mlink-bitcode-file" ".*asanrtl.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" +// NORDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* .* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" // NORDC: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} -// RDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" +// RDC: {{"[^"]*clang[^"]*".* "-emit-llvm-bc".* "-fcuda-is-device".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" // RDC: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} // FAIL: error: cannot find ROCm device library for ABI version 5; provide its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build without ROCm device library @@ -113,7 +113,7 @@ // XNACK-DAG: warning: ignoring '-fsanitize=leak' option as it is not currently supported for target 'amdgcn-amd-amdhsa' // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 'gfx900:xnack-' as it is not currently supported there. Use it with an offload arch containing 'xnack+' instead // XNACK-DAG: warning: ignoring '-fsanitize=address' option for offload arch 'gfx906' as it is not currently supported there. Use it with an offload arch containing 'xnack+' instead -// XNACK-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} +// XNACK-DAG: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} // XNACK-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} // XNACK-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906"}} // XNACK-DAG: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address,leak"}} @@ -122,8 +122,8 @@ // XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address,leak"}} // XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack".* "-fsanitize=address"}} // XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address"}} -// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} -// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx906"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} +// XNACKNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx906"}} // XNACKNEG-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}} // NOGPU-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack"}} @@ -133,21 +133,21 @@ // NOGPUNEG-NOT: warning: ignoring '-fsanitize=leak' option as it is not currently supported for target 'amdgcn-amd-amdhsa' // NOGPUNEG-NOT: warning: ignoring '-fsanitize=address' option for offload arch 'gfx900:xnack-' as it is not currently supported there. Use it with an offload arch containing 'xnack+' instead // NOGPUNEG-NOT: warning: ignoring '-fsanitize=address' option for offload arch 'gfx906' as it is not currently supported there. Use it with an offload arch containing 'xnack+' instead -// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} +// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address,leak"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack".* "-fsanitize=address,leak"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address,leak"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx900".* "-target-feature" "-xnack".* "-fsanitize=address"}} // NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx906".* "-fsanitize=address"}} -// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack"}} -// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} -// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx906"}} +// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack"}} +// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "-xnack"}} +// NOGPUNEG-NOT: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx906"}} // NOGPUNEG-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}} // INVALIDCOMBINATION1-DAG: warning: ignoring 'fuzzer' in '-fsanitize=address,fuzzer' option as it is not currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored] // INVALIDCOMBINATION2-DAG: warning: ignoring 'fuzzer' in '-fsanitize=fuzzer,address' option as it is not currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored] -// INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} +// INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} // INVALIDCOMBINATION-DAG: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address,fuzzer,fuzzer-no-link"}} // MULT1-DAG: warning: ignoring 'fuzzer' in '-fsanitize=address,fuzzer' option as it is not currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored] @@ -162,7 +162,7 @@ // MULT2-DAG: warning: ignoring '-fsanitize=fuzzer,address' option for offload arch 'gfx908:xnack-' as it is not currently supported there. Use it with an offload arch containing 'xnack+' instead [-Woption-ignored] // MULT2-DAG: warning: ignoring '-fsanitize=leak' option as it is not currently supported for target 'amdgcn-amd-amdhsa' [-Woption-ignored] -// XNACK2-DAG: {{"[^"]*clang[^"]*".* "-mlink-bitcode-file" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} +// XNACK2-DAG: {{"[^"]*clang[^"]*".* "-mlink-builtin-bitcode" ".*asanrtl.bc".* "-target-cpu" "gfx900".* "-target-feature" "\+xnack".* "-fsanitize=address"}} // XNACK2-DAG: {{"[^"]*clang[^"]*".* "-target-cpu" "gfx908"}} // XNACK2-DAG: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address,fuzzer,fuzzer-no-link,leak"}} diff --git a/clang/test/Driver/rocm-device-libs.cl b/clang/test/Driver/rocm-device-libs.cl index 232f36df38768..50c924fc11d0a 100644 --- a/clang/test/Driver/rocm-device-libs.cl +++ b/clang/test/Driver/rocm-device-libs.cl @@ -164,7 +164,7 @@ // COMMON: "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/opencl.bc" -// ASAN-SAME: "-mlink-bitcode-file" "{{.*}}/amdgcn/bitcode/asanrtl.bc" +// ASAN-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/asanrtl.bc" // COMMON-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/ocml.bc" // COMMON-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/ockl.bc" From 5661ed60e37d63d5deff6f4c943b928b6b957049 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Fri, 27 Feb 2026 18:50:22 +0100 Subject: [PATCH 13/58] [mlir][vector] Fix crashes in MaskOp::fold and CanonializeEmptyMaskOp (#183781) Two related crashes were fixed in vector.mask handling: 1. MaskOp::fold() crashes with a null pointer dereference when the mask is all-true and the mask body has no maskable operation (only a vector.yield). getMaskableOp() returns nullptr in this case, and the fold was calling nullptr->dropAllUses(). Fixed by returning failure() when there is no maskable op, deferring to the canonicalizer. 2. CanonializeEmptyMaskOp creates an invalid arith.select when the mask type is a vector (e.g., vector<1xi1>) but the result type is a scalar (e.g., i32). arith.select with a vector condition requires the value types to be vectors of the same shape. Fixed by bailing out when any result type doesn't match the mask shape. Regression tests are added for both cases. Fixes #177833 --- mlir/lib/Dialect/Vector/IR/VectorOps.cpp | 15 ++++++++++ mlir/test/Dialect/Vector/canonicalize.mlir | 33 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp index aa6734049bbd7..b935ad77c1c14 100644 --- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp +++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp @@ -7630,7 +7630,11 @@ LogicalResult MaskOp::fold(FoldAdaptor adaptor, return failure(); // Move maskable operation outside of the `vector.mask` region. + // If there is no maskable op (empty body), the fold cannot proceed; the + // canonicalizer handles this case instead. Operation *maskableOp = getMaskableOp(); + if (!maskableOp) + return failure(); maskableOp->dropAllUses(); maskableOp->moveBefore(getOperation()); @@ -7661,6 +7665,17 @@ class CanonializeEmptyMaskOp : public OpRewritePattern { if (!maskOp.hasPassthru()) return failure(); + // arith.select with a vector condition requires the value types to be + // vectors of the same shape. Since vector.mask always has a vector mask + // type, bail out when any result type doesn't match the mask shape to + // avoid creating invalid IR. + VectorType maskType = maskOp.getMask().getType(); + for (Type resultType : maskOp.getResultTypes()) { + auto vecResultType = dyn_cast(resultType); + if (!vecResultType || vecResultType.getShape() != maskType.getShape()) + return failure(); + } + Block *block = maskOp.getMaskBlock(); auto terminator = cast(block->front()); assert(terminator.getNumOperands() == 1 && diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir index 82b2cb633d1c9..3980c179b5d0a 100644 --- a/mlir/test/Dialect/Vector/canonicalize.mlir +++ b/mlir/test/Dialect/Vector/canonicalize.mlir @@ -4082,3 +4082,36 @@ func.func @extract_strided_slice_outer_shorter(%arg0: vector<4x8x16xf32>) -> vec %1 = vector.extract_strided_slice %0 {offsets = [0], sizes = [2], strides = [1]} : vector<3x4x16xf32> to vector<2x4x16xf32> return %1 : vector<2x4x16xf32> } + +// ----- + +// Regression test for https://github.com/llvm/llvm-project/issues/177833: +// CanonializeEmptyMaskOp must not create arith.select with a vector condition +// and scalar value types (incompatible with arith.select semantics). The +// vector.mask op should remain unchanged. +// +// CHECK-LABEL: func @no_fold_empty_mask_scalar_result_with_passthru +// CHECK-SAME: %[[MASK:.*]]: vector<1xi1>, %[[PASSTHRU:.*]]: i32, %[[VAL:.*]]: i32 +// CHECK: vector.mask %[[MASK]], %[[PASSTHRU]] { vector.yield %[[VAL]] : i32 } : vector<1xi1> -> i32 +// CHECK-NOT: arith.select +func.func @no_fold_empty_mask_scalar_result_with_passthru( + %mask : vector<1xi1>, %passthru : i32, %val : i32) -> i32 { + %result = vector.mask %mask, %passthru { vector.yield %val : i32 } : vector<1xi1> -> i32 + return %result : i32 +} + +// ----- + +// Regression test for https://github.com/llvm/llvm-project/issues/177833: +// MaskOp::fold must not crash with a null pointer dereference when the mask +// is all-true and the mask body has no maskable op (only a yield). +// +// CHECK-LABEL: func @no_fold_alltrue_mask_empty_body_scalar_result +// CHECK-SAME: %[[PASSTHRU:.*]]: i32, %[[VAL:.*]]: i32 +// CHECK: vector.mask +func.func @no_fold_alltrue_mask_empty_body_scalar_result( + %passthru : i32, %val : i32) -> i32 { + %all_true = vector.constant_mask [1] : vector<1xi1> + %result = vector.mask %all_true, %passthru { vector.yield %val : i32 } : vector<1xi1> -> i32 + return %result : i32 +} From 55d62abadbc5e6bf129378fe9d0b87f124aefee5 Mon Sep 17 00:00:00 2001 From: Ilia Kuklin Date: Fri, 27 Feb 2026 22:59:03 +0500 Subject: [PATCH 14/58] [lldb] Add arithmetic binary addition to DIL (#177208) --- lldb/docs/dil-expr-lang.ebnf | 4 +- lldb/include/lldb/ValueObject/DILAST.h | 35 +++ lldb/include/lldb/ValueObject/DILEval.h | 24 ++ lldb/include/lldb/ValueObject/DILParser.h | 1 + lldb/source/ValueObject/DILAST.cpp | 14 ++ lldb/source/ValueObject/DILEval.cpp | 222 ++++++++++++++++++ lldb/source/ValueObject/DILParser.cpp | 24 +- .../Arithmetic/TestFrameVarDILArithmetic.py | 47 +++- .../frame/var-dil/expr/Arithmetic/main.cpp | 18 ++ 9 files changed, 386 insertions(+), 3 deletions(-) diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf index 99a8b0fcaa006..127c1d6337efa 100644 --- a/lldb/docs/dil-expr-lang.ebnf +++ b/lldb/docs/dil-expr-lang.ebnf @@ -3,7 +3,9 @@ (* This is currently a subset of the final DIL Language, matching the current DIL implementation. *) -expression = cast_expression; +expression = additive_expression ; + +additive_expression = cast_expression {"+" cast_expression} ; cast_expression = unary_expression | "(" type_id ")" cast_expression; diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index da7659959093a..226f80ac70c5e 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -9,6 +9,7 @@ #ifndef LLDB_VALUEOBJECT_DILAST_H #define LLDB_VALUEOBJECT_DILAST_H +#include "lldb/ValueObject/DILLexer.h" #include "lldb/ValueObject/ValueObject.h" #include "llvm/Support/Error.h" #include @@ -19,6 +20,7 @@ namespace lldb_private::dil { /// The various types DIL AST nodes (used by the DIL parser). enum class NodeKind { eArraySubscriptNode, + eBinaryOpNode, eBitExtractionNode, eBooleanLiteralNode, eCastNode, @@ -38,6 +40,14 @@ enum class UnaryOpKind { Plus, // "+" }; +/// The binary operators recognized by DIL. +enum class BinaryOpKind { + Add, // "+" +}; + +/// Translates DIL tokens to BinaryOpKind. +BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind); + /// The type casts allowed by DIL. enum class CastKind { eArithmetic, ///< Casting to a scalar. @@ -148,6 +158,29 @@ class UnaryOpNode : public ASTNode { ASTNodeUP m_operand; }; +class BinaryOpNode : public ASTNode { +public: + BinaryOpNode(uint32_t location, BinaryOpKind kind, ASTNodeUP lhs, + ASTNodeUP rhs) + : ASTNode(location, NodeKind::eBinaryOpNode), m_kind(kind), + m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) {} + + llvm::Expected Accept(Visitor *v) const override; + + BinaryOpKind GetKind() const { return m_kind; } + ASTNode &GetLHS() const { return *m_lhs; } + ASTNode &GetRHS() const { return *m_rhs; } + + static bool classof(const ASTNode *node) { + return node->GetKind() == NodeKind::eBinaryOpNode; + } + +private: + BinaryOpKind m_kind; + ASTNodeUP m_lhs; + ASTNodeUP m_rhs; +}; + class ArraySubscriptNode : public ASTNode { public: ArraySubscriptNode(uint32_t location, ASTNodeUP base, ASTNodeUP index) @@ -292,6 +325,8 @@ class Visitor { virtual llvm::Expected Visit(const UnaryOpNode &node) = 0; virtual llvm::Expected + Visit(const BinaryOpNode &node) = 0; + virtual llvm::Expected Visit(const ArraySubscriptNode &node) = 0; virtual llvm::Expected Visit(const BitFieldExtractionNode &node) = 0; diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 550f5083b1dc6..54d33129908a3 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -57,6 +57,7 @@ class Interpreter : Visitor { Visit(const IdentifierNode &node) override; llvm::Expected Visit(const MemberOfNode &node) override; llvm::Expected Visit(const UnaryOpNode &node) override; + llvm::Expected Visit(const BinaryOpNode &node) override; llvm::Expected Visit(const ArraySubscriptNode &node) override; llvm::Expected @@ -73,6 +74,29 @@ class Interpreter : Visitor { /// includes array-to-pointer and integral promotion for eligible types. llvm::Expected UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location); + + /// If `lhs_type` is unsigned and `rhs_type` is signed, check whether it + /// can represent all of the values of `lhs_type`. + /// If not, then promote `rhs_type` to the unsigned version of its type. + /// This expects that Rank(lhs_type) < Rank(rhs_type). + /// \returns Unchanged `rhs_type` or promoted unsigned version. + llvm::Expected PromoteSignedInteger(CompilerType &lhs_type, + CompilerType &rhs_type); + + /// Perform an arithmetic conversion on two values from an arithmetic + /// operation. + /// \returns The result type of an arithmetic operation. + llvm::Expected ArithmeticConversion(lldb::ValueObjectSP &lhs, + lldb::ValueObjectSP &rhs, + uint32_t location); + llvm::Expected EvaluateScalarOp(BinaryOpKind kind, + lldb::ValueObjectSP lhs, + lldb::ValueObjectSP rhs, + CompilerType result_type, + uint32_t location); + llvm::Expected + EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, + uint32_t location); llvm::Expected PickIntegerType(lldb::TypeSystemSP type_system, std::shared_ptr ctx, diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h index 3bac4b2bb4171..d093f95cde841 100644 --- a/lldb/include/lldb/ValueObject/DILParser.h +++ b/lldb/include/lldb/ValueObject/DILParser.h @@ -94,6 +94,7 @@ class DILParser { ASTNodeUP Run(); ASTNodeUP ParseExpression(); + ASTNodeUP ParseAdditiveExpression(); ASTNodeUP ParseUnaryExpression(); ASTNodeUP ParsePostfixExpression(); ASTNodeUP ParsePrimaryExpression(); diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp index d8a714d33712d..180708f79c269 100644 --- a/lldb/source/ValueObject/DILAST.cpp +++ b/lldb/source/ValueObject/DILAST.cpp @@ -11,6 +11,16 @@ namespace lldb_private::dil { +BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind) { + switch (token_kind) { + case Token::plus: + return BinaryOpKind::Add; + default: + break; + } + llvm_unreachable("Unknown binary operator kind."); +} + llvm::Expected ErrorNode::Accept(Visitor *v) const { llvm_unreachable("Attempting to Visit a DIL ErrorNode."); } @@ -27,6 +37,10 @@ llvm::Expected UnaryOpNode::Accept(Visitor *v) const { return v->Visit(*this); } +llvm::Expected BinaryOpNode::Accept(Visitor *v) const { + return v->Visit(*this); +} + llvm::Expected ArraySubscriptNode::Accept(Visitor *v) const { return v->Visit(*this); diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index 187cc9bb16180..acefb5dc6133b 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -127,6 +127,151 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) { return valobj; } +/// Basic types with a lower rank are converted to the basic type +/// with a higher rank. +static size_t ConversionRank(CompilerType type) { + switch (type.GetCanonicalType().GetBasicTypeEnumeration()) { + case lldb::eBasicTypeBool: + return 1; + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + return 2; + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + return 3; + case lldb::eBasicTypeInt: + case lldb::eBasicTypeUnsignedInt: + return 4; + case lldb::eBasicTypeLong: + case lldb::eBasicTypeUnsignedLong: + return 5; + case lldb::eBasicTypeLongLong: + case lldb::eBasicTypeUnsignedLongLong: + return 6; + case lldb::eBasicTypeInt128: + case lldb::eBasicTypeUnsignedInt128: + return 7; + case lldb::eBasicTypeHalf: + return 8; + case lldb::eBasicTypeFloat: + return 9; + case lldb::eBasicTypeDouble: + return 10; + case lldb::eBasicTypeLongDouble: + return 11; + default: + break; + } + return 0; +} + +static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type) { + switch (basic_type) { + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + return lldb::eBasicTypeUnsignedChar; + case lldb::eBasicTypeShort: + return lldb::eBasicTypeUnsignedShort; + case lldb::eBasicTypeInt: + return lldb::eBasicTypeUnsignedInt; + case lldb::eBasicTypeLong: + return lldb::eBasicTypeUnsignedLong; + case lldb::eBasicTypeLongLong: + return lldb::eBasicTypeUnsignedLongLong; + case lldb::eBasicTypeInt128: + return lldb::eBasicTypeUnsignedInt128; + default: + return basic_type; + } +} + +llvm::Expected +Interpreter::PromoteSignedInteger(CompilerType &lhs_type, + CompilerType &rhs_type) { + assert(lhs_type.IsInteger() && rhs_type.IsInteger()); + if (!lhs_type.IsSigned() && rhs_type.IsSigned()) { + llvm::Expected lhs_size = + lhs_type.GetBitSize(m_exe_ctx_scope.get()); + if (!lhs_size) + return lhs_size.takeError(); + llvm::Expected rhs_size = + rhs_type.GetBitSize(m_exe_ctx_scope.get()); + if (!rhs_size) + return rhs_size.takeError(); + + if (*rhs_size == *lhs_size) { + llvm::Expected type_system = + GetTypeSystemFromCU(m_exe_ctx_scope); + if (!type_system) + return type_system.takeError(); + CompilerType r_type_unsigned = GetBasicType( + *type_system, + BasicTypeToUnsigned( + rhs_type.GetCanonicalType().GetBasicTypeEnumeration())); + return r_type_unsigned; + } + } + return rhs_type; +} + +llvm::Expected +Interpreter::ArithmeticConversion(lldb::ValueObjectSP &lhs, + lldb::ValueObjectSP &rhs, uint32_t location) { + // Apply unary conversion for both operands. + auto lhs_or_err = UnaryConversion(lhs, location); + if (!lhs_or_err) + return lhs_or_err.takeError(); + lhs = *lhs_or_err; + auto rhs_or_err = UnaryConversion(rhs, location); + if (!rhs_or_err) + return rhs_or_err.takeError(); + rhs = *rhs_or_err; + + CompilerType lhs_type = lhs->GetCompilerType(); + CompilerType rhs_type = rhs->GetCompilerType(); + + // If types already match, no need for further conversions. + if (lhs_type.CompareTypes(rhs_type)) + return lhs_type; + + // If either of the operands is not arithmetic (e.g. pointer), we're done. + if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType()) + return CompilerType(); + + size_t l_rank = ConversionRank(lhs_type); + size_t r_rank = ConversionRank(rhs_type); + if (l_rank == 0 || r_rank == 0) + return llvm::make_error( + m_expr, "unexpected basic type in arithmetic operation", location); + + // If both operands are integer, check if we need to promote + // the higher ranked signed type. + if (lhs_type.IsInteger() && rhs_type.IsInteger()) { + using Rank = std::tuple; + Rank int_l_rank = {l_rank, !lhs_type.IsSigned()}; + Rank int_r_rank = {r_rank, !rhs_type.IsSigned()}; + if (int_l_rank < int_r_rank) { + auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type); + if (!type_or_err) + return type_or_err.takeError(); + return *type_or_err; + } + if (int_l_rank > int_r_rank) { + auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type); + if (!type_or_err) + return type_or_err.takeError(); + return *type_or_err; + } + return lhs_type; + } + + // Handle other combinations of integer and floating point operands. + if (l_rank < r_rank) + return rhs_type; + return lhs_type; +} + static lldb::VariableSP DILFindVariable(ConstString name, VariableList &variable_list) { lldb::VariableSP exact_match; @@ -393,6 +538,83 @@ Interpreter::Visit(const UnaryOpNode &node) { node.GetLocation()); } +llvm::Expected +Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, + lldb::ValueObjectSP rhs, CompilerType result_type, + uint32_t location) { + Scalar l, r; + bool l_resolved = lhs->ResolveValue(l); + bool r_resolved = rhs->ResolveValue(r); + + if (!l_resolved || !r_resolved) + return llvm::make_error(m_expr, "invalid scalar value", + location); + + auto value_object = [this, result_type](Scalar scalar) { + return ValueObject::CreateValueObjectFromScalar(m_target, scalar, + result_type, "result"); + }; + + switch (kind) { + case BinaryOpKind::Add: + return value_object(l + r); + } + return llvm::make_error( + m_expr, "invalid arithmetic operation", location); +} + +llvm::Expected Interpreter::EvaluateBinaryAddition( + lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) { + // Operation '+' works for: + // {scalar,unscoped_enum} <-> {scalar,unscoped_enum} + // TODO: Pointer arithmetics + auto orig_lhs_type = lhs->GetCompilerType(); + auto orig_rhs_type = rhs->GetCompilerType(); + auto type_or_err = ArithmeticConversion(lhs, rhs, location); + if (!type_or_err) + return type_or_err.takeError(); + CompilerType result_type = *type_or_err; + + if (result_type.IsScalarType()) + return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location); + + std::string errMsg = + llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')", + orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName()); + return llvm::make_error(m_expr, std::move(errMsg), + location); +} + +llvm::Expected +Interpreter::Visit(const BinaryOpNode &node) { + auto lhs_or_err = EvaluateAndDereference(node.GetLHS()); + if (!lhs_or_err) + return lhs_or_err; + lldb::ValueObjectSP lhs = *lhs_or_err; + auto rhs_or_err = EvaluateAndDereference(node.GetRHS()); + if (!rhs_or_err) + return rhs_or_err; + lldb::ValueObjectSP rhs = *rhs_or_err; + + lldb::TypeSystemSP lhs_system = + lhs->GetCompilerType().GetTypeSystem().GetSharedPointer(); + lldb::TypeSystemSP rhs_system = + rhs->GetCompilerType().GetTypeSystem().GetSharedPointer(); + if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) { + // TODO: Attempt to convert values to current CU's type system + return llvm::make_error( + m_expr, "operands have different type systems", node.GetLocation()); + } + + switch (node.GetKind()) { + case BinaryOpKind::Add: + return EvaluateBinaryAddition(lhs, rhs, node.GetLocation()); + } + + return llvm::make_error( + m_expr, "unimplemented binary operation", node.GetLocation()); +} + llvm::Expected Interpreter::Visit(const MemberOfNode &node) { auto base_or_err = Evaluate(node.GetBase()); diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index df8d4d271c410..f07607c93d927 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -127,7 +127,29 @@ ASTNodeUP DILParser::Run() { // expression: // cast_expression // -ASTNodeUP DILParser::ParseExpression() { return ParseCastExpression(); } +ASTNodeUP DILParser::ParseExpression() { return ParseAdditiveExpression(); } + +// Parse an additive_expression. +// +// additive_expression: +// cast_expression {"+" cast_expression} +// +ASTNodeUP DILParser::ParseAdditiveExpression() { + auto lhs = ParseCastExpression(); + assert(lhs && "ASTNodeUP must not contain a nullptr"); + + while (CurToken().Is(Token::plus)) { + Token token = CurToken(); + m_dil_lexer.Advance(); + auto rhs = ParseCastExpression(); + assert(rhs && "ASTNodeUP must not contain a nullptr"); + lhs = std::make_unique( + token.GetLocation(), GetBinaryOpKindFromToken(token.GetKind()), + std::move(lhs), std::move(rhs)); + } + + return lhs; +} // Parse a cast_expression. // diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py index 53a85fed303f4..5b68c493ba3a5 100644 --- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py @@ -13,7 +13,7 @@ class TestFrameVarDILArithmetic(TestBase): def test_arithmetic(self): self.build() - lldbutil.run_to_source_breakpoint( + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") ) @@ -44,3 +44,48 @@ def test_arithmetic(self): self.expect_var_path("+bitfield.b", value="2", type="int") self.expect_var_path("+bitfield.c", value="3", type="unsigned int") self.expect_var_path("+bitfield.d", value="4", type="uint64_t") + + # Check basic math and resulting types + self.expect_var_path("1 + 2", value="3", type="int") + self.expect_var_path("1 + true", value="2", type="int") + self.expect_var_path("1L + wchar", value="2", type="long") + self.expect_var_path("1L + char16", value="3", type="long") + self.expect_var_path("1LL + char32", value="4", type="long long") + self.expect_var_path("1UL + 1L", value="2", type="unsigned long") + self.expect_var_path("s + x", value="12", type="int") + self.expect_var_path("s + l", value="15", type="long") + self.expect_var_path("l + ul", value="11", type="unsigned long") + self.expect_var_path("1.0 + 2.5", value="3.5", type="double") + self.expect_var_path("1 + 2.5f", value="3.5", type="float") + self.expect_var_path("2. + .5", value="2.5", type="double") + self.expect_var_path("2.f + .5f", value="2.5", type="float") + self.expect_var_path("f + d", value="3.5", type="double") + self.expect_var_path("1 + s + (x + l)", value="18", type="long") + self.expect_var_path("+2 + (-1)", value="1", type="int") + self.expect_var_path("-2 + (+1)", value="-1", type="int") + + # Check limits and overflows + frame = thread.GetFrameAtIndex(0) + int_min = frame.GetValueForVariablePath("int_min").GetValue() + ll_min = frame.GetValueForVariablePath("ll_min").GetValue() + self.expect_var_path("int_max + 1", value=int_min) + self.expect_var_path("uint_max + 1", value="0") + self.expect_var_path("ll_max + 1", value=ll_min) + self.expect_var_path("ull_max + 1", value="0") + + # Check signed integer promotion when different types have the same size + uint = frame.GetValueForVariablePath("ui") + long = frame.GetValueForVariablePath("l") + if uint.GetByteSize() == long.GetByteSize(): + self.expect_var_path("ui + l", value="9", type="unsigned long") + self.expect_var_path("l + ui", value="9", type="unsigned long") + ulong = frame.GetValueForVariablePath("ul") + longlong = frame.GetValueForVariablePath("ll") + if ulong.GetByteSize() == longlong.GetByteSize(): + self.expect_var_path("ul + ll", value="13", type="unsigned long long") + self.expect_var_path("ll + ul", value="13", type="unsigned long long") + + # Check references and typedefs + self.expect_var_path("ref + 1", value="3") + self.expect_var_path("my_ref + 1", value="3") + self.expect_var_path("ref + my_ref", value="4") diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp index 2c70e93433f5f..f41b89beb2bde 100644 --- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp @@ -1,11 +1,22 @@ #include +#include int main(int argc, char **argv) { short s = 10; unsigned short us = 1; + unsigned int ui = 4; + long l = 5; + unsigned long ul = 6; + long long ll = 7; + float f = 1.0f; + double d = 2.5; int x = 2; int &ref = x; + int *p = &x; + typedef int &myref; + myref my_ref = x; + enum Enum { kZero, kOne } enum_one = kOne; wchar_t wchar = 1; char16_t char16 = 2; @@ -19,5 +30,12 @@ int main(int argc, char **argv) { }; BitFieldStruct bitfield = {1, 2, 3, 4}; + int int_max = std::numeric_limits::max(); + int int_min = std::numeric_limits::min(); + unsigned int uint_max = std::numeric_limits::max(); + long long ll_max = std::numeric_limits::max(); + long long ll_min = std::numeric_limits::min(); + unsigned long long ull_max = std::numeric_limits::max(); + return 0; // Set a breakpoint here } From d2c545266b8b0216b51c7b87e3ca0980c47c5342 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 27 Feb 2026 09:59:56 -0800 Subject: [PATCH 15/58] [RISCV] Use getCopyFromReg in unit test to match comment. NFC (#183199) Using physical register 0, aka NoRegister, also just looked suspicious. --- llvm/unittests/Target/RISCV/RISCVSelectionDAGTest.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/Target/RISCV/RISCVSelectionDAGTest.cpp b/llvm/unittests/Target/RISCV/RISCVSelectionDAGTest.cpp index 9c61aae358278..31c36fa5261ab 100644 --- a/llvm/unittests/Target/RISCV/RISCVSelectionDAGTest.cpp +++ b/llvm/unittests/Target/RISCV/RISCVSelectionDAGTest.cpp @@ -102,10 +102,12 @@ TEST_F(RISCVSelectionDAGTest, computeKnownBits_SRLW) { // The DAG created below is derived from this SDLoc Loc; auto Int64VT = EVT::getIntegerVT(Context, 64); - auto Px = DAG->getRegister(0, Int64VT); + auto Px = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, + Register::index2VirtReg(0), Int64VT); auto Py = DAG->getConstant(2147483647, Loc, Int64VT); auto N1 = DAG->getNode(ISD::AND, Loc, Int64VT, Px, Py); - auto Qx = DAG->getRegister(0, Int64VT); + auto Qx = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, + Register::index2VirtReg(1), Int64VT); auto N2 = DAG->getNode(RISCVISD::SRLW, Loc, Int64VT, N1, Qx); auto Py2 = DAG->getConstant(4294967295, Loc, Int64VT); auto N3 = DAG->getNode(ISD::AND, Loc, Int64VT, N2, Py2); From cd50a3074bdfcd2d9ba45d99b0129b1c1d68d58d Mon Sep 17 00:00:00 2001 From: yonghong-song Date: Fri, 27 Feb 2026 10:04:30 -0800 Subject: [PATCH 16/58] Revert "[ThinLTO] Reduce the number of renaming due to promotions (#178587)" (#183782) There is a conflict with existing code. See https://github.com/llvm/llvm-project/pull/178587 Revert and resolve the conflict and then will submit later. --- .../distributed-thin-lto/cfi-devirt.ll | 2 +- .../test/CodeGen/distributed-thin-lto/cfi.ll | 2 +- clang/test/CodeGen/thinlto-funcattr-prop.ll | 4 +- lld/test/ELF/lto/comdat-nodeduplicate.ll | 8 +- llvm/include/llvm/AsmParser/LLToken.h | 1 - llvm/include/llvm/IR/ModuleSummaryIndex.h | 21 +--- llvm/include/llvm/IR/ModuleSummaryIndexYAML.h | 14 +-- llvm/include/llvm/LTO/LTO.h | 3 +- .../llvm/Transforms/IPO/WholeProgramDevirt.h | 6 +- .../Transforms/Utils/FunctionImportUtils.h | 3 +- llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 10 +- llvm/lib/AsmParser/LLLexer.cpp | 1 - llvm/lib/AsmParser/LLParser.cpp | 12 +-- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 4 +- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 - llvm/lib/IR/AsmWriter.cpp | 1 - llvm/lib/IR/ModuleSummaryIndex.cpp | 2 - llvm/lib/LTO/LTO.cpp | 59 ++--------- .../lib/Transforms/IPO/WholeProgramDevirt.cpp | 29 ++---- .../Transforms/Utils/FunctionImportUtils.cpp | 24 +---- .../test/Assembler/thinlto-memprof-summary.ll | 24 ++--- .../thinlto-multiple-summaries-for-guid.ll | 4 +- .../Assembler/thinlto-summary-visibility.ll | 6 +- llvm/test/Assembler/thinlto-summary.ll | 60 +++++------ llvm/test/Assembler/thinlto-vtable-summary.ll | 4 +- llvm/test/Bitcode/thinlto-alias.ll | 10 +- ...ction-summary-callgraph-profile-summary.ll | 18 ++-- ...hinlto-function-summary-callgraph-relbf.ll | 2 +- .../thinlto-function-summary-refgraph.ll | 14 +-- .../thinlto-index-disassembled-by-llvm-dis.ll | 2 +- llvm/test/Bitcode/thinlto-type-tests.ll | 12 +-- llvm/test/Bitcode/thinlto-type-vcalls.ll | 24 ++--- .../reduce-promotion-same-file-local-name.ll | 20 ---- .../ThinLTO/X86/funcattrs-prop-maythrow.ll | 6 +- .../ThinLTO/X86/funcimport_alwaysinline.ll | 2 +- .../ThinLTO/X86/import_callee_declaration.ll | 8 +- llvm/test/ThinLTO/X86/load-store-caching.ll | 4 +- .../ThinLTO/X86/reduce-promotion-devirt.ll | 99 ------------------- .../reduce-promotion-same-file-local-name.ll | 46 --------- .../X86/reduce-promotion-same-local-name.ll | 69 ------------- llvm/test/ThinLTO/X86/reduce-promotion.ll | 56 ----------- .../Transforms/LowerTypeTests/import-unsat.ll | 1 - .../Inputs/import-indir.yaml | 1 - .../WholeProgramDevirt/import-indir.ll | 2 - 44 files changed, 147 insertions(+), 555 deletions(-) delete mode 100644 llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll delete mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll delete mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll delete mode 100644 llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll delete mode 100644 llvm/test/ThinLTO/X86/reduce-promotion.ll diff --git a/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll b/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll index 14938cbaa465b..a5792eee8abfb 100644 --- a/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll +++ b/clang/test/CodeGen/distributed-thin-lto/cfi-devirt.ll @@ -34,7 +34,7 @@ ; Round trip it through llvm-as ; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS ; CHECK-DIS: ^0 = module: (path: "{{.*}}cfi-devirt.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}})) -; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0)))))) +; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0)))))) ; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi"))))) ; guid = 7004155349499253778 ; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \ diff --git a/clang/test/CodeGen/distributed-thin-lto/cfi.ll b/clang/test/CodeGen/distributed-thin-lto/cfi.ll index 585602d43c79d..696f2dc4ea634 100644 --- a/clang/test/CodeGen/distributed-thin-lto/cfi.ll +++ b/clang/test/CodeGen/distributed-thin-lto/cfi.ll @@ -24,7 +24,7 @@ ; Round trip it through llvm-as ; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS ; CHECK-DIS: ^0 = module: (path: "{{.*}}cfi.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}})) -; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2))))) +; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2))))) ; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 7004155349499253778 ; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \ diff --git a/clang/test/CodeGen/thinlto-funcattr-prop.ll b/clang/test/CodeGen/thinlto-funcattr-prop.ll index e5f39ddd58a4f..daaa6e2da8048 100644 --- a/clang/test/CodeGen/thinlto-funcattr-prop.ll +++ b/clang/test/CodeGen/thinlto-funcattr-prop.ll @@ -15,9 +15,9 @@ ; RUN: llvm-dis %t1.o.1.1.promote.bc -o - | FileCheck %s --check-prefix=CHECK-IR ;; Summary for call_extern. Note that llvm-lto2 writes out the index before propagation occurs so call_extern doesn't have its flags updated. -; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^3))))) +; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^3))))) ;; Summary for extern -; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) ;--- a.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/lld/test/ELF/lto/comdat-nodeduplicate.ll b/lld/test/ELF/lto/comdat-nodeduplicate.ll index 96a78aa175e41..928da5c82e518 100644 --- a/lld/test/ELF/lto/comdat-nodeduplicate.ll +++ b/lld/test/ELF/lto/comdat-nodeduplicate.ll @@ -62,15 +62,15 @@ ; IR_AB-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]] ;; Check extra attributes. b.bc:__profc_foo is prevailing, so it can be internalized. -; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), -; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), +; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) ; IR_ABC-DAG: gv: (name: "__profd_foo", {{.*}} guid = [[PROFD:[0-9]+]] ; IR_ABC-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]] ;; b.bc:__profc_foo prevails c.bc:__profc_foo, so it is exported and therefore not internalized. -; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), -; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), +; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) ;--- a.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 6c92c82188f1a..5d5d70f89bde5 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -404,7 +404,6 @@ enum Kind { kw_importType, kw_definition, kw_declaration, - kw_noRenameOnPromotion, kw_function, kw_insts, kw_funcFlags, diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index b0b5ef9908a5e..5ede26cc7923c 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -269,8 +269,6 @@ struct ValueInfo { /// Checks if all copies are eligible for auto-hiding (have flag set). LLVM_ABI bool canAutoHide() const; - - LLVM_ABI bool noRenameOnPromotion() const; }; inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) { @@ -515,21 +513,15 @@ class GlobalValueSummary { /// transition unsigned Promoted : 1; - /// This field is written by the ThinLTO prelink stage to decide whether - /// a particular static global value should be promoted or not. - unsigned NoRenameOnPromotion : 1; - /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, GlobalValue::VisibilityTypes Visibility, bool NotEligibleToImport, bool Live, bool IsLocal, - bool CanAutoHide, ImportKind ImportType, - bool NoRenameOnPromotion) + bool CanAutoHide, ImportKind ImportType) : Linkage(Linkage), Visibility(Visibility), NotEligibleToImport(NotEligibleToImport), Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide), - ImportType(static_cast(ImportType)), Promoted(false), - NoRenameOnPromotion(NoRenameOnPromotion) {} + ImportType(static_cast(ImportType)), Promoted(false) {} }; private: @@ -639,12 +631,6 @@ class GlobalValueSummary { void setImportKind(ImportKind IK) { Flags.ImportType = IK; } - void setNoRenameOnPromotion(bool NoRenameOnPromotion) { - Flags.NoRenameOnPromotion = NoRenameOnPromotion; - } - - bool noRenameOnPromotion() const { return Flags.NoRenameOnPromotion; } - GlobalValueSummary::ImportKind importType() const { return static_cast(Flags.ImportType); } @@ -913,8 +899,7 @@ class FunctionSummary : public GlobalValueSummary { GlobalValue::LinkageTypes::AvailableExternallyLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false, - /*CanAutoHide=*/false, GlobalValueSummary::ImportKind::Definition, - /*NoRenameOnPromotion=*/false), + /*CanAutoHide=*/false, GlobalValueSummary::ImportKind::Definition), /*NumInsts=*/0, FunctionSummary::FFlags{}, SmallVector(), std::move(Edges), std::vector(), std::vector(), diff --git a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h index 546dbb6b64e20..ccb77e75492af 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -140,7 +140,7 @@ template <> struct MappingTraits { struct GlobalValueSummaryYaml { // Commonly used fields unsigned Linkage, Visibility; - bool NotEligibleToImport, Live, IsLocal, CanAutoHide, NoRenameOnPromotion; + bool NotEligibleToImport, Live, IsLocal, CanAutoHide; unsigned ImportType; // Fields for AliasSummary std::optional Aliasee; @@ -191,7 +191,6 @@ template <> struct MappingTraits { io.mapOptional("Local", summary.IsLocal); io.mapOptional("CanAutoHide", summary.CanAutoHide); io.mapOptional("ImportType", summary.ImportType); - io.mapOptional("NoRenameOnPromotion", summary.NoRenameOnPromotion); io.mapOptional("Aliasee", summary.Aliasee); io.mapOptional("Refs", summary.Refs); io.mapOptional("TypeTests", summary.TypeTests); @@ -229,8 +228,7 @@ template <> struct CustomMappingTraits { static_cast(GVSum.Visibility), GVSum.NotEligibleToImport, GVSum.Live, GVSum.IsLocal, GVSum.CanAutoHide, - static_cast(GVSum.ImportType), - GVSum.NoRenameOnPromotion); + static_cast(GVSum.ImportType)); if (GVSum.Aliasee) { auto ASum = std::make_unique(GVFlags); V.try_emplace(*GVSum.Aliasee, /*IsAnalysis=*/false); @@ -274,10 +272,9 @@ template <> struct CustomMappingTraits { static_cast(FSum->flags().Live), static_cast(FSum->flags().DSOLocal), static_cast(FSum->flags().CanAutoHide), - FSum->flags().ImportType, - static_cast(FSum->flags().NoRenameOnPromotion), - /*Aliasee=*/std::nullopt, Refs, FSum->type_tests(), - FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), + FSum->flags().ImportType, /*Aliasee=*/std::nullopt, Refs, + FSum->type_tests(), FSum->type_test_assume_vcalls(), + FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), FSum->type_checked_load_const_vcalls()}); } else if (auto *ASum = dyn_cast(Sum.get()); @@ -289,7 +286,6 @@ template <> struct CustomMappingTraits { static_cast(ASum->flags().DSOLocal), static_cast(ASum->flags().CanAutoHide), ASum->flags().ImportType, - static_cast(ASum->flags().NoRenameOnPromotion), /*Aliasee=*/ASum->getAliaseeGUID()}); } } diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 38349b604b6b3..3e877d22c3f6c 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -65,8 +65,7 @@ LLVM_ABI void thinLTOInternalizeAndPromoteInIndex( ModuleSummaryIndex &Index, function_ref isExported, function_ref - isPrevailing, - DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); + isPrevailing); /// Computes a unique hash for the Module considering the current list of /// export/import and other global analysis results. diff --git a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h index ba0b22b799ebe..2e33a4098be1b 100644 --- a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -271,16 +271,14 @@ LLVM_ABI void getVisibleToRegularObjVtableGUIDs( /// devirtualized target name will need adjustment). LLVM_ABI void runWholeProgramDevirtOnIndex( ModuleSummaryIndex &Summary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap, - DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); + std::map> &LocalWPDTargetsMap); /// Call after cross-module importing to update the recorded single impl /// devirt target names for any locals that were exported. LLVM_ABI void updateIndexWPDForExports( ModuleSummaryIndex &Summary, function_ref isExported, - std::map> &LocalWPDTargetsMap, - DenseSet *ExternallyVisibleSymbolNamesPtr = nullptr); + std::map> &LocalWPDTargetsMap); } // end namespace llvm diff --git a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h index e22bea53a18a6..c4c7b403bed86 100644 --- a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -63,8 +63,7 @@ class FunctionImportGlobalProcessing { DenseMap RenamedComdats; /// Check if we should promote the given local value to global scope. - bool shouldPromoteLocalToGlobal(const GlobalValue *SGV, - GlobalValueSummary *Summary); + bool shouldPromoteLocalToGlobal(const GlobalValue *SGV, ValueInfo VI); #ifndef NDEBUG /// Check if the given value is a local that can't be renamed (promoted). diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index f504519ebb5a6..069f4ae1790b1 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -712,8 +712,7 @@ static void computeFunctionSummary( GlobalValueSummary::GVFlags Flags( F.getLinkage(), F.getVisibility(), NotEligibleForImport, /* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(), - GlobalValueSummary::ImportKind::Definition, - /* NoRenameOnPromotion = */ false); + GlobalValueSummary::ImportKind::Definition); FunctionSummary::FFlags FunFlags{ F.doesNotAccessMemory(), F.onlyReadsMemory() && !F.doesNotAccessMemory(), F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(), @@ -871,7 +870,7 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, GlobalValueSummary::GVFlags Flags( V.getLinkage(), V.getVisibility(), NonRenamableLocal, /* Live = */ false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition, /* NoRenameOnPromotion = */ false); + GlobalValueSummary::Definition); VTableFuncList VTableFuncs; // If splitting is not enabled, then we compute the summary information @@ -918,7 +917,7 @@ static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, GlobalValueSummary::GVFlags Flags( A.getLinkage(), A.getVisibility(), NonRenamableLocal, /* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition, /* NoRenameOnPromotion = */ false); + GlobalValueSummary::Definition); auto AS = std::make_unique(Flags); auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID()); assert(AliaseeVI && "Alias expects aliasee summary to be available"); @@ -1000,8 +999,7 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex( /* NotEligibleToImport = */ true, /* Live = */ true, /* Local */ GV->isDSOLocal(), GV->canBeOmittedFromSymbolTable(), - GlobalValueSummary::Definition, - /* NoRenameOnPromotion = */ false); + GlobalValueSummary::Definition); CantBePromoted.insert(GV->getGUID()); // Create the appropriate summary type. if (Function *F = dyn_cast(GV)) { diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 4840d04f6b78d..8d20ff72a8505 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -809,7 +809,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(importType); KEYWORD(definition); KEYWORD(declaration); - KEYWORD(noRenameOnPromotion); KEYWORD(function); KEYWORD(insts); KEYWORD(funcFlags); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 551b88d8b435b..09b030b28dce8 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -10023,7 +10023,7 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); + GlobalValueSummary::Definition); unsigned InstCount; SmallVector Calls; FunctionSummary::TypeIdInfo TypeIdInfo; @@ -10111,7 +10111,7 @@ bool LLParser::parseVariableSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); + GlobalValueSummary::Definition); GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false, /* WriteOnly */ false, /* Constant */ false, @@ -10170,7 +10170,7 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID, GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false, - GlobalValueSummary::Definition, /*NoRenameOnPromotion=*/false); + GlobalValueSummary::Definition); if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseModuleReference(ModulePath) || @@ -10967,12 +10967,6 @@ bool LLParser::parseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { GVFlags.ImportType = static_cast(IK); Lex.Lex(); break; - case lltok::kw_noRenameOnPromotion: - Lex.Lex(); - if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) - return true; - GVFlags.NoRenameOnPromotion = Flag; - break; default: return error(Lex.getLoc(), "expected gv flag type"); } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index a781a43112f8c..c0807c7be3e4f 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1175,7 +1175,6 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags, auto Linkage = GlobalValue::LinkageTypes(RawFlags & 0xF); // 4 bits auto Visibility = GlobalValue::VisibilityTypes((RawFlags >> 8) & 3); // 2 bits auto IK = GlobalValueSummary::ImportKind((RawFlags >> 10) & 1); // 1 bit - bool NoRenameOnPromotion = ((RawFlags >> 11) & 1); // 1 bit RawFlags = RawFlags >> 4; bool NotEligibleToImport = (RawFlags & 0x1) || Version < 3; // The Live flag wasn't introduced until version 3. For dead stripping @@ -1186,8 +1185,7 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags, bool AutoHide = (RawFlags & 0x8); return GlobalValueSummary::GVFlags(Linkage, Visibility, NotEligibleToImport, - Live, Local, AutoHide, IK, - NoRenameOnPromotion); + Live, Local, AutoHide, IK); } // Decode the flags for GlobalVariable in the summary diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index f0316116d0107..cc0491bd8577f 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1337,8 +1337,6 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags, unsigned ImportType = Flags.ImportType | ImportAsDecl; RawFlags |= (ImportType << 10); // 1 bit - RawFlags |= (Flags.NoRenameOnPromotion << 11); // 1 bit - return RawFlags; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index dd99b14d45d6e..35a19091aa097 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -3730,7 +3730,6 @@ void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) { Out << ", canAutoHide: " << GVFlags.CanAutoHide; Out << ", importType: " << getImportTypeName(GlobalValueSummary::ImportKind(GVFlags.ImportType)); - Out << ", noRenameOnPromotion: " << GVFlags.NoRenameOnPromotion; Out << ")"; if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind) diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp index 98876c87ef6db..9a3bb970494a2 100644 --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -686,8 +686,6 @@ void ModuleSummaryIndex::exportToDot( A.addComment("definition"); else if (Flags.ImportType == GlobalValueSummary::ImportKind::Declaration) A.addComment("declaration"); - if (Flags.NoRenameOnPromotion) - A.addComment("noRenameOnPromotion"); if (GUIDPreservedSymbols.count(SummaryIt.first)) A.addComment("preserved"); diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index bf2d2e6b9da9d..853f6427f9c8c 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -110,7 +110,6 @@ static cl::opt namespace llvm { extern cl::opt CodeGenDataThinLTOTwoRounds; extern cl::opt ForceImportAll; -extern cl::opt AlwaysRenamePromotedLocals; } // end namespace llvm namespace llvm { @@ -510,8 +509,7 @@ void llvm::thinLTOResolvePrevailingInIndex( static void thinLTOInternalizeAndPromoteGUID( ValueInfo VI, function_ref isExported, function_ref - isPrevailing, - DenseSet *ExternallyVisibleSymbolNamesPtr) { + isPrevailing) { // Before performing index-based internalization and promotion for this GUID, // the local flag should be consistent with the summary list linkage types. VI.verifyLocal(); @@ -520,24 +518,12 @@ static void thinLTOInternalizeAndPromoteGUID( VI.getSummaryList().size() == 1 && !GlobalValue::isLocalLinkage(VI.getSummaryList().front()->linkage()); - bool NameRecorded = false; for (auto &S : VI.getSummaryList()) { // First see if we need to promote an internal value because it is not // exported. if (isExported(S->modulePath(), VI)) { - if (GlobalValue::isLocalLinkage(S->linkage())) { - // Only the first local GlobalValue in a list of summaries does not - // need renaming. In rare cases if there exist more than one summaries - // in the list, the rest of them must have renaming (through promotion) - // to avoid conflict. - if (ExternallyVisibleSymbolNamesPtr && !NameRecorded) { - NameRecorded = true; - if (ExternallyVisibleSymbolNamesPtr->insert(VI.name()).second) - S->setNoRenameOnPromotion(true); - } - + if (GlobalValue::isLocalLinkage(S->linkage())) S->promote(); - } continue; } @@ -607,14 +593,11 @@ void llvm::thinLTOInternalizeAndPromoteInIndex( ModuleSummaryIndex &Index, function_ref isExported, function_ref - isPrevailing, - DenseSet *ExternallyVisibleSymbolNamesPtr) { + isPrevailing) { assert(!Index.withInternalizeAndPromote()); - for (auto &I : Index) thinLTOInternalizeAndPromoteGUID(Index.getValueInfo(I), isExported, - isPrevailing, - ExternallyVisibleSymbolNamesPtr); + isPrevailing); Index.setWithInternalizeAndPromote(); } @@ -2064,19 +2047,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, // no index entries in the typeIdMetadata map (e.g. if we are instead // performing IR-based WPD in hybrid regular/thin LTO mode). std::map> LocalWPDTargetsMap; - DenseSet ExternallyVisibleSymbolNames; - - // Used by the promotion-time renaming logic. When non-null, this set - // identifies symbols that should not be renamed during promotion. - // It is non-null only when whole-program visibility is enabled and - // renaming is not forced. Otherwise, the default renaming behavior applies. - DenseSet *ExternallyVisibleSymbolNamesPtr = - (WholeProgramVisibilityEnabledInLTO && !AlwaysRenamePromotedLocals) - ? &ExternallyVisibleSymbolNames - : nullptr; runWholeProgramDevirtOnIndex(ThinLTO.CombinedIndex, ExportedGUIDs, - LocalWPDTargetsMap, - ExternallyVisibleSymbolNamesPtr); + LocalWPDTargetsMap); auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { return ThinLTO.isPrevailingModuleForGUID(GUID, S->modulePath()); @@ -2136,27 +2108,10 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, // Update local devirtualized targets that were exported by cross-module // importing or by other devirtualizations marked in the ExportedGUIDs set. updateIndexWPDForExports(ThinLTO.CombinedIndex, isExported, - LocalWPDTargetsMap, ExternallyVisibleSymbolNamesPtr); - - if (ExternallyVisibleSymbolNamesPtr) { - // Add to ExternallyVisibleSymbolNames the set of unique names used by all - // externally visible symbols in the index. - for (auto &I : ThinLTO.CombinedIndex) { - ValueInfo VI = ThinLTO.CombinedIndex.getValueInfo(I); - for (const auto &Summary : VI.getSummaryList()) { - const GlobalValueSummary *Base = Summary->getBaseObject(); - if (GlobalValue::isLocalLinkage(Base->linkage())) - continue; - - ExternallyVisibleSymbolNamesPtr->insert(VI.name()); - break; - } - } - } + LocalWPDTargetsMap); thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported, - isPrevailing, - ExternallyVisibleSymbolNamesPtr); + isPrevailing); auto recordNewLinkage = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID, diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index e057761256775..8c2420a45a24c 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -773,11 +773,6 @@ struct DevirtIndex { // resolution for local targets in case they are exported by cross module // importing. std::map> &LocalWPDTargetsMap; - // We have hardcoded the promoted and renamed function name in the WPD - // summary, so we need to ensure that they will be renamed. Note this and - // that adding the current names to this set ensures we continue to rename - // them. - DenseSet *ExternallyVisibleSymbolNamesPtr; MapVector CallSlots; @@ -786,11 +781,9 @@ struct DevirtIndex { DevirtIndex( ModuleSummaryIndex &ExportSummary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap, - DenseSet *ExternallyVisibleSymbolNamesPtr) + std::map> &LocalWPDTargetsMap) : ExportSummary(ExportSummary), ExportedGUIDs(ExportedGUIDs), - LocalWPDTargetsMap(LocalWPDTargetsMap), - ExternallyVisibleSymbolNamesPtr(ExternallyVisibleSymbolNamesPtr) { + LocalWPDTargetsMap(LocalWPDTargetsMap) { FunctionsToSkip.init(SkipFunctionNames); } @@ -980,18 +973,14 @@ void llvm::updateVCallVisibilityInIndex( void llvm::runWholeProgramDevirtOnIndex( ModuleSummaryIndex &Summary, std::set &ExportedGUIDs, - std::map> &LocalWPDTargetsMap, - DenseSet *ExternallyVisibleSymbolNamesPtr) { - DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap, - ExternallyVisibleSymbolNamesPtr) - .run(); + std::map> &LocalWPDTargetsMap) { + DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap).run(); } void llvm::updateIndexWPDForExports( ModuleSummaryIndex &Summary, function_ref IsExported, - std::map> &LocalWPDTargetsMap, - DenseSet *ExternallyVisibleSymbolNamesPtr) { + std::map> &LocalWPDTargetsMap) { for (auto &T : LocalWPDTargetsMap) { auto &VI = T.first; // This was enforced earlier during trySingleImplDevirt. @@ -1007,8 +996,6 @@ void llvm::updateIndexWPDForExports( assert(TIdSum); auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset); assert(WPDRes != TIdSum->WPDRes.end()); - if (ExternallyVisibleSymbolNamesPtr) - ExternallyVisibleSymbolNamesPtr->insert(WPDRes->second.SingleImplName); WPDRes->second.SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal( WPDRes->second.SingleImplName, Summary.getModuleHash(S->modulePath())); @@ -1442,15 +1429,13 @@ bool DevirtIndex::trySingleImplDevirt(MutableArrayRef TargetsForSlot, // step. Res->TheKind = WholeProgramDevirtResolution::SingleImpl; if (GlobalValue::isLocalLinkage(S->linkage())) { - if (IsExported) { + if (IsExported) // If target is a local function and we are exporting it by // devirtualizing a call in another module, we need to record the // promoted name. - if (ExternallyVisibleSymbolNamesPtr) - ExternallyVisibleSymbolNamesPtr->insert(TheFn.name()); Res->SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal( TheFn.name(), ExportSummary.getModuleHash(S->modulePath())); - } else { + else { LocalWPDTargetsMap[TheFn].push_back(SlotSummary); Res->SingleImplName = std::string(TheFn.name()); } diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp index 475699c42b21e..d31154fcf085d 100644 --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -28,14 +28,6 @@ static cl::opt UseSourceFilenameForPromotedLocals( "This requires that the source filename has a unique name / " "path to avoid name collisions.")); -/// FIXME: The current optimization that avoids unnecessary renaming of -/// promoted locals is incompatible with distributed ThinLTO and therefore -/// must be enabled by default. -cl::opt - AlwaysRenamePromotedLocals("always-rename-promoted-locals", cl::init(true), - cl::Hidden, - cl::desc("Always rename promoted locals.")); - cl::list MoveSymbolGUID( "thinlto-move-symbols", cl::desc( @@ -89,7 +81,7 @@ bool FunctionImportGlobalProcessing::doImportAsDefinition( } bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal( - const GlobalValue *SGV, GlobalValueSummary *Summary) { + const GlobalValue *SGV, ValueInfo VI) { assert(SGV->hasLocalLinkage()); // Ifuncs and ifunc alias does not have summary. @@ -120,6 +112,8 @@ bool FunctionImportGlobalProcessing::shouldPromoteLocalToGlobal( // same-named source files that were compiled in their respective directories // (so the source file name and resulting GUID is the same). Find the one // in this module. + auto Summary = ImportIndex.findSummaryInModule( + VI, SGV->getParent()->getModuleIdentifier()); assert(Summary && "Missing summary for global value when exporting"); auto Linkage = Summary->linkage(); if (!GlobalValue::isLocalLinkage(Linkage)) { @@ -312,18 +306,10 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { } } - GlobalValueSummary *Summary = nullptr; - if (VI && GV.hasLocalLinkage()) - Summary = ImportIndex.findSummaryInModule( - VI, GV.getParent()->getModuleIdentifier()); - - if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, Summary)) { + if (GV.hasLocalLinkage() && shouldPromoteLocalToGlobal(&GV, VI)) { // Save the original name string before we rename GV below. auto Name = GV.getName().str(); - if (AlwaysRenamePromotedLocals || !Summary || - !Summary->noRenameOnPromotion()) - GV.setName(getPromotedName(&GV)); - + GV.setName(getPromotedName(&GV)); GV.setLinkage(getLinkage(&GV, /* DoPromote */ true)); assert(!GV.hasLocalLinkage()); GV.setVisibility(GlobalValue::HiddenVisibility); diff --git a/llvm/test/Assembler/thinlto-memprof-summary.ll b/llvm/test/Assembler/thinlto-memprof-summary.ll index 225fda60f8550..4e4a928c1f024 100644 --- a/llvm/test/Assembler/thinlto-memprof-summary.ll +++ b/llvm/test/Assembler/thinlto-memprof-summary.ll @@ -12,22 +12,22 @@ ^0 = module: (path: "thinlto-memprof-summary.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ;; Function with single alloc, multiple memprof MIBs, no versioning -^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) +^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) ;; Function with callsite stack ids calling above function, no versioning -^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) +^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) ;; Function with multiple allocs, multiple memprof MIBs, multiple versions -^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) +^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) ;; Function with callsite stack ids calling above function, multiple versions -^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) +^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) ;; Function with null callsite stack id (can happen in distributed indexes if callsite not imported) -^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) +^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) ; Make sure we get back from llvm-dis what we put in via llvm-as. ; CHECK: ^0 = module: (path: "thinlto-memprof-summary.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) -; CONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) -; NOCONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()), (type: hot, stackIds: ()))))))) -; CHECK: ^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) -; CONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) -; NOCONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: ()), (type: notcold, stackIds: ()))))))) -; CHECK: ^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) -; CHECK: ^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) +; CONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: (8632435727821051414)), (type: cold, stackIds: (15025054523792398438, 12345678)), (type: hot, stackIds: (987654321)))))))) +; NOCONTEXT: ^1 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (none), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()), (type: hot, stackIds: ()))))))) +; CHECK: ^2 = gv: (guid: 25, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^1)), callsites: ((callee: ^1, clones: (0), stackIds: (8632435727821051414)), (callee: ^1, clones: (0), stackIds: (15025054523792398438, 12345678)), (callee: ^1, clones: (0), stackIds: (23456789)))))) +; CONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: (3456789)), (type: cold, stackIds: (456789)))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: (3456789)), (type: notcold, stackIds: (456789)))))))) +; NOCONTEXT: ^3 = gv: (guid: 26, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), allocs: ((versions: (cold, notcold), memProf: ((type: notcold, stackIds: ()), (type: cold, stackIds: ()))), (versions: (notcold, cold), memProf: ((type: cold, stackIds: ()), (type: notcold, stackIds: ()))))))) +; CHECK: ^4 = gv: (guid: 27, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^3)), callsites: ((callee: ^3, clones: (0, 1), stackIds: (3456789)), (callee: ^3, clones: (1, 1), stackIds: (456789)))))) +; CHECK: ^5 = gv: (guid: 28, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 22, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), callsites: ((callee: null, clones: (0), stackIds: (8632435727821051414)))))) diff --git a/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll b/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll index 83e0c8cbc8a13..117280a279d09 100644 --- a/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll +++ b/llvm/test/Assembler/thinlto-multiple-summaries-for-guid.ll @@ -8,5 +8,5 @@ source_filename = "index.bc" ; CHECK: ^0 = module: (path: "[Regular LTO]", hash: (0, 0, 0, 0, 0)) ^1 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952)) ; CHECK-NEXT: ^1 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952)) -^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1), function: (module: ^1, flags: (linkage: available_externally, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK-NEXT: ^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1), function: (module: ^1, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1), function: (module: ^1, flags: (linkage: available_externally, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK-NEXT: ^2 = gv: (guid: 13351721993301222997, summaries: (function: (module: ^1, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1), function: (module: ^1, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) diff --git a/llvm/test/Assembler/thinlto-summary-visibility.ll b/llvm/test/Assembler/thinlto-summary-visibility.ll index 08f7d06433505..67ddcb961d7ae 100644 --- a/llvm/test/Assembler/thinlto-summary-visibility.ll +++ b/llvm/test/Assembler/thinlto-summary-visibility.ll @@ -4,9 +4,9 @@ ^0 = module: (path: "thinlto-summary-visibility1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ^1 = module: (path: "thinlto-summary-visibility2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156)) -; CHECK: ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) -; CHECK-NEXT: ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) -; CHECK-NEXT: ^4 = gv: (guid: 4, summaries: (function: (module: ^0, flags: (linkage: external, visibility: hidden, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10))) +; CHECK: ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) +; CHECK-NEXT: ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) +; CHECK-NEXT: ^4 = gv: (guid: 4, summaries: (function: (module: ^0, flags: (linkage: external, visibility: hidden, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10))) ^2 = gv: (guid: 2, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default), insts: 10))) ^3 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: external, visibility: protected), insts: 10))) diff --git a/llvm/test/Assembler/thinlto-summary.ll b/llvm/test/Assembler/thinlto-summary.ll index 5b907f9a06039..21da14850b962 100644 --- a/llvm/test/Assembler/thinlto-summary.ll +++ b/llvm/test/Assembler/thinlto-summary.ll @@ -17,13 +17,13 @@ ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, relbf: 256, tail: 1))))) ; Summaries with different linkage types. -^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) +^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1))) ; Make this one an alias with a forward reference to aliasee. -^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) +^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), aliasee: ^14))) ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) -^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) +^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition), insts: 1))) ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1))) ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0)))) ; Test appending globel variable with reference (tests backward reference on @@ -54,14 +54,14 @@ ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) ; Function summary with an import type of declaration -^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, importType: declaration, noRenameOnPromotion: 0), insts: 5))) +^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, importType: declaration), insts: 5))) ; Alias summary with null aliasee. ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: null))) ; GUID that are 64-bit -^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) +^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1))) ; Test TypeId summaries: @@ -80,33 +80,33 @@ ; Make sure we get back from llvm-dis essentially what we put in via llvm-as. ; CHECK: ^0 = module: (path: "thinlto-summary1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049)) ; CHECK: ^1 = module: (path: "thinlto-summary2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156)) -; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none, tail: 1)), refs: (^11, readonly ^13, writeonly ^14)))) +; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none, tail: 1)), refs: (^11, readonly ^13, writeonly ^14)))) ;; relbf is not emitted since this is a combined summary, and that is only ;; emitted for per-module summaries. Additionally, it is now deprecated. -; CHECK: ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 10, calls: ((callee: ^15, tail: 1))))) -; CHECK: ^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) -; CHECK: ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) -; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^4)))) -; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 0, constant: 0)))) -; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) -; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) -; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 1, hasUnknownCall: 1, mustBeUnreachable: 0)))) -; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 1), calls: ((callee: ^15))))) -; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^14))) -; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (^27, ^29))))) -; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^30, offset: 16)))))) -; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^28, offset: 16)))))) -; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^30, offset: 16), args: (42)), (vFuncId: (^30, offset: 24))))))) -; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) -; CHECK: ^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: declaration, noRenameOnPromotion: 0), insts: 5))) -; CHECK: ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: null))) -; CHECK: ^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; CHECK: ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 10, calls: ((callee: ^15, tail: 1))))) +; CHECK: ^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: ^14))) +; CHECK: ^6 = gv: (guid: 5, summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^7 = gv: (guid: 6, summaries: (function: (module: ^0, flags: (linkage: linkonce, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1, importType: definition), insts: 1))) +; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^4)))) +; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 0, constant: 0)))) +; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0)))) +; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 1, hasUnknownCall: 1, mustBeUnreachable: 0)))) +; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 1), calls: ((callee: ^15))))) +; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: ^14))) +; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (^27, ^29))))) +; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^30, offset: 16)))))) +; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^28, offset: 16)))))) +; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^30, offset: 16), args: (42)), (vFuncId: (^30, offset: 24))))))) +; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^31, offset: 16), args: (42))))))) +; CHECK: ^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: declaration), insts: 5))) +; CHECK: ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: null))) +; CHECK: ^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1))) ; CHECK: ^27 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584 ; CHECK: ^28 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976 ; CHECK: ^29 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778 diff --git a/llvm/test/Assembler/thinlto-vtable-summary.ll b/llvm/test/Assembler/thinlto-vtable-summary.ll index 7b8e4f2a928a4..80720287f7a09 100644 --- a/llvm/test/Assembler/thinlto-vtable-summary.ll +++ b/llvm/test/Assembler/thinlto-vtable-summary.ll @@ -29,9 +29,9 @@ declare i32 @_ZN1C1fEi(ptr, i32) ^0 = module: (path: "", hash: (0, 0, 0, 0, 0)) ^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257 -^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367 +^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367 ^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394 -^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296 +^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296 ^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556 ^6 = typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778 ^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976 diff --git a/llvm/test/Bitcode/thinlto-alias.ll b/llvm/test/Bitcode/thinlto-alias.ll index 4191983055b2c..7deb2d8259e32 100644 --- a/llvm/test/Bitcode/thinlto-alias.ll +++ b/llvm/test/Bitcode/thinlto-alias.ll @@ -53,11 +53,11 @@ entry: declare void @analias(...) ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) -; DIS: ^1 = gv: (name: "analias", summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^2))) ; guid = 12695095382722328222 -; DIS: ^2 = gv: (name: "aliasee", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) ; guid = 17407585008595848568 +; DIS: ^1 = gv: (name: "analias", summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), aliasee: ^2))) ; guid = 12695095382722328222 +; DIS: ^2 = gv: (name: "aliasee", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) ; guid = 17407585008595848568 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-alias.ll.tmp.o", hash: (0, 0, 0, 0, 0)) ; COMBINED-DIS: ^1 = module: (path: "{{.*}}thinlto-alias.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^2 = gv: (guid: 12695095382722328222, summaries: (alias: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), aliasee: ^4))) -; COMBINED-DIS: ^3 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^2))))) -; COMBINED-DIS: ^4 = gv: (guid: 17407585008595848568, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^2 = gv: (guid: 12695095382722328222, summaries: (alias: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), aliasee: ^4))) +; COMBINED-DIS: ^3 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^2))))) +; COMBINED-DIS: ^4 = gv: (guid: 17407585008595848568, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll index 33288be2d2195..576261e5392b2 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll @@ -150,16 +150,16 @@ declare void @none3() #1 ; DIS: ^6 = gv: (name: "cold") ; guid = 11668175513417606517 ; DIS: ^7 = gv: (name: "hot4") ; guid = 13161834114071272798 ; DIS: ^8 = gv: (name: "none3") ; guid = 16213681105727317812 -; DIS: ^9 = gv: (name: "hot_function", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^7, hotness: cold), (callee: ^10, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^8, hotness: none), (callee: ^1, hotness: critical))))) ; guid = 17381606045411660303 +; DIS: ^9 = gv: (name: "hot_function", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^7, hotness: cold), (callee: ^10, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^8, hotness: none), (callee: ^1, hotness: critical))))) ; guid = 17381606045411660303 ; DIS: ^10 = gv: (name: "none1") ; guid = 17712061229457633252 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-function-summary-callgraph-profile-summary.ll.tmp.o", hash: (0, 0, 0, 0, 0)) ; COMBINED-DIS: ^1 = module: (path: "{{.*}}thinlto-function-summary-callgraph-profile-summary.ll.tmp2.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^2 = gv: (guid: 3741006263754194003, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^3 = gv: (guid: 5026609803865204483, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^4 = gv: (guid: 8117347573235780485, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^5 = gv: (guid: 9453975128311291976, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^6 = gv: (guid: 11668175513417606517, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^7 = gv: (guid: 16213681105727317812, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) -; COMBINED-DIS: ^8 = gv: (guid: 17381606045411660303, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^9, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^7, hotness: none))))) -; COMBINED-DIS: ^9 = gv: (guid: 17712061229457633252, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1))) +; COMBINED-DIS: ^2 = gv: (guid: 3741006263754194003, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^3 = gv: (guid: 5026609803865204483, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^4 = gv: (guid: 8117347573235780485, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^5 = gv: (guid: 9453975128311291976, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^6 = gv: (guid: 11668175513417606517, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^7 = gv: (guid: 16213681105727317812, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) +; COMBINED-DIS: ^8 = gv: (guid: 17381606045411660303, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 16, calls: ((callee: ^5, hotness: hot), (callee: ^6, hotness: cold), (callee: ^4, hotness: hot), (callee: ^9, hotness: none), (callee: ^3, hotness: hot), (callee: ^2, hotness: none), (callee: ^7, hotness: none))))) +; COMBINED-DIS: ^9 = gv: (guid: 17712061229457633252, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1))) diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll index d50bad6cbc128..22e27c45324af 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-relbf.ll @@ -39,5 +39,5 @@ declare void @func(...) #1 ; DIS: ^1 = gv: (name: "func") ; guid = 7289175272376759421 ;; We should have ignored the relbf in the old bitcode, and it no longer shows ;; up in the summary. -; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 3, calls: ((callee: ^1)), refs: (readonly ^3)))) ; guid = 15822663052811949562 +; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 3, calls: ((callee: ^1)), refs: (readonly ^3)))) ; guid = 15822663052811949562 ; DIS: ^3 = gv: (name: "undefinedglob") ; guid = 18036901804029949403 diff --git a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll index a25901a572d30..c76d70b8c4cc0 100644 --- a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll +++ b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll @@ -148,18 +148,18 @@ entry: ; order, which depends on GUID, and the private function Y GUID will depend ; on the path to the test. ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) -; DIS-DAG: = gv: (name: "Z", summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = 104084381700047393 -; DIS-DAG: = gv: (name: "X", summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 1881667236089500162 -; DIS-DAG: = gv: (name: "W", summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, calls: ((callee: ^{{.*}}, tail: 1)), refs: (^{{.*}})))) ; guid = 5790125716599269729 +; DIS-DAG: = gv: (name: "Z", summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = 104084381700047393 +; DIS-DAG: = gv: (name: "X", summaries: (function: (module: ^0, flags: (linkage: available_externally, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 1881667236089500162 +; DIS-DAG: = gv: (name: "W", summaries: (function: (module: ^0, flags: (linkage: weak_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^{{.*}}, tail: 1)), refs: (^{{.*}})))) ; guid = 5790125716599269729 ; DIS-DAG: = gv: (name: "foo") ; guid = 6699318081062747564 ; DIS-DAG: = gv: (name: "func") ; guid = 7289175272376759421 ; DIS-DAG: = gv: (name: "func3") ; guid = 11517462787082255043 ; Check that default value of writeonly attribute is zero for constant variables -; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 0, constant: 1)))) ; guid = 12887606300320728018 +; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 0, constant: 1)))) ; guid = 12887606300320728018 ; DIS-DAG: = gv: (name: "func2") ; guid = 14069196320850861797 ; DIS-DAG: = gv: (name: "llvm.ctpop.i8") ; guid = 15254915475081819833 -; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 9, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562 -; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0), refs: (^{{.*}})))) ; guid = 16434608426314478903 +; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 9, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562 +; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 1, constant: 0), refs: (^{{.*}})))) ; guid = 16434608426314478903 ; Don't try to match the exact GUID. Since it is private, the file path ; will get hashed, and that will be test dependent. -; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 14, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = +; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 14, calls: ((callee: ^{{.*}}, tail: 1))))) ; guid = diff --git a/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll index 74980ad76304c..3f71a3dfe0591 100644 --- a/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll +++ b/llvm/test/Bitcode/thinlto-index-disassembled-by-llvm-dis.ll @@ -18,7 +18,7 @@ ; RUN: llvm-dis --print-thinlto-index-only %t.o -o - | FileCheck %s --check-prefix=DIS ; DIS: ^0 = module: (path: "{{.*}}thinlto-index-disassembled-by-llvm-dis.ll.tmp -; DIS: ^1 = gv: (name: "aplusb", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2))) ; guid = +; DIS: ^1 = gv: (name: "aplusb", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2))) ; guid = source_filename = "add.cpp" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/Bitcode/thinlto-type-tests.ll b/llvm/test/Bitcode/thinlto-type-tests.ll index 6d329d5bce949..6dc49b849c2fe 100644 --- a/llvm/test/Bitcode/thinlto-type-tests.ll +++ b/llvm/test/Bitcode/thinlto-type-tests.ll @@ -37,11 +37,11 @@ declare i1 @llvm.type.test(i8*, metadata) nounwind readnone ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) ; DIS: ^1 = gv: (name: "llvm.type.test") ; guid = 608142985856744218 -; DIS: ^2 = gv: (name: "h", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) ; guid = 8124147457056772133 -; DIS: ^3 = gv: (name: "g", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) ; guid = 13146401226427987378 -; DIS: ^4 = gv: (name: "f", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) ; guid = 14740650423002898831 +; DIS: ^2 = gv: (name: "h", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) ; guid = 8124147457056772133 +; DIS: ^3 = gv: (name: "g", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) ; guid = 13146401226427987378 +; DIS: ^4 = gv: (name: "f", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) ; guid = 14740650423002898831 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-type-tests.ll.tmp.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^1 = gv: (guid: 8124147457056772133, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) -; COMBINED-DIS: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) -; COMBINED-DIS: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) +; COMBINED-DIS: ^1 = gv: (guid: 8124147457056772133, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (16434608426314478903))))) +; COMBINED-DIS: ^2 = gv: (guid: 13146401226427987378, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, typeIdInfo: (typeTests: (6699318081062747564, 16434608426314478903))))) +; COMBINED-DIS: ^3 = gv: (guid: 14740650423002898831, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (6699318081062747564))))) diff --git a/llvm/test/Bitcode/thinlto-type-vcalls.ll b/llvm/test/Bitcode/thinlto-type-vcalls.ll index f10f6535c7f08..16c93097101df 100644 --- a/llvm/test/Bitcode/thinlto-type-vcalls.ll +++ b/llvm/test/Bitcode/thinlto-type-vcalls.ll @@ -112,19 +112,19 @@ declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata) ; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) ; DIS: ^1 = gv: (name: "llvm.type.test") ; guid = 608142985856744218 -; DIS: ^2 = gv: (name: "f1", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 2072045998141807037 -; DIS: ^3 = gv: (name: "f3", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 4197650231481825559 +; DIS: ^2 = gv: (name: "f1", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 2072045998141807037 +; DIS: ^3 = gv: (name: "f3", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) ; guid = 4197650231481825559 ; DIS: ^4 = gv: (name: "llvm.type.checked.load") ; guid = 5568222536364573403 ; DIS: ^5 = gv: (name: "llvm.assume") ; guid = 6385187066495850096 -; DIS: ^6 = gv: (name: "f2", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) ; guid = 8471399308421654326 -; DIS: ^7 = gv: (name: "f4", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) ; guid = 10064745020953272174 -; DIS: ^8 = gv: (name: "f5", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) ; guid = 11686717102184386164 -; DIS: ^9 = gv: (name: "f6", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) ; guid = 11834966808443348068 +; DIS: ^6 = gv: (name: "f2", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) ; guid = 8471399308421654326 +; DIS: ^7 = gv: (name: "f4", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) ; guid = 10064745020953272174 +; DIS: ^8 = gv: (name: "f5", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) ; guid = 11686717102184386164 +; DIS: ^9 = gv: (name: "f6", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) ; guid = 11834966808443348068 ; COMBINED-DIS: ^0 = module: (path: "{{.*}}thinlto-type-vcalls.ll.tmp.o", hash: (0, 0, 0, 0, 0)) -; COMBINED-DIS: ^1 = gv: (guid: 2072045998141807037, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) -; COMBINED-DIS: ^2 = gv: (guid: 4197650231481825559, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) -; COMBINED-DIS: ^3 = gv: (guid: 8471399308421654326, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) -; COMBINED-DIS: ^4 = gv: (guid: 10064745020953272174, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) -; COMBINED-DIS: ^5 = gv: (guid: 11686717102184386164, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) -; COMBINED-DIS: ^6 = gv: (guid: 11834966808443348068, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) +; COMBINED-DIS: ^1 = gv: (guid: 2072045998141807037, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 8, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) +; COMBINED-DIS: ^2 = gv: (guid: 4197650231481825559, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (guid: 6699318081062747564, offset: 16)))))) +; COMBINED-DIS: ^3 = gv: (guid: 8471399308421654326, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (guid: 6699318081062747564, offset: 24), vFuncId: (guid: 16434608426314478903, offset: 32)))))) +; COMBINED-DIS: ^4 = gv: (guid: 10064745020953272174, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42)), (vFuncId: (guid: 6699318081062747564, offset: 24), args: (43))))))) +; COMBINED-DIS: ^5 = gv: (guid: 11686717102184386164, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (guid: 6699318081062747564, offset: 16), args: (42))))))) +; COMBINED-DIS: ^6 = gv: (guid: 11834966808443348068, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 2, typeIdInfo: (typeTests: (7546896869197086323))))) diff --git a/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll b/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll deleted file mode 100644 index 5906da234b199..0000000000000 --- a/llvm/test/ThinLTO/X86/Inputs/reduce-promotion-same-file-local-name.ll +++ /dev/null @@ -1,20 +0,0 @@ -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-pc-linux-gnu" - -source_filename = "foo.c" - -define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { - %2 = tail call fastcc i32 @foo(i32 noundef %0) - %3 = shl nsw i32 %0, 1 - %4 = tail call fastcc i32 @foo(i32 noundef %3) - %5 = add nsw i32 %4, %2 - ret i32 %5 -} - -define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { - %2 = add nsw i32 %0, 5 - %3 = sdiv i32 %2, %0 - ret i32 %3 -} - -attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll index 5475ca1bf1d44..abfe820075bb9 100644 --- a/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll +++ b/llvm/test/ThinLTO/X86/funcattrs-prop-maythrow.ll @@ -48,9 +48,9 @@ define void @caller_nounwind() { ; CHECK-DAG: attributes [[ATTR_NOUNWIND]] = { norecurse nounwind } ; CHECK-DAG: attributes [[ATTR_MAYTHROW]] = { norecurse } -; SUMMARY-DAG: = gv: (name: "cleanupret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) -; SUMMARY-DAG: = gv: (name: "resume", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) -; SUMMARY-DAG: = gv: (name: "catchret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "cleanupret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "resume", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) +; SUMMARY-DAG: = gv: (name: "catchret", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 1, hasUnknownCall: 0, mustBeUnreachable: 0), calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ;--- callees.ll target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll b/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll index 431e2a9254887..67acc2a2892db 100644 --- a/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll +++ b/llvm/test/ThinLTO/X86/funcimport_alwaysinline.ll @@ -23,4 +23,4 @@ entry: } attributes #0 = { alwaysinline nounwind uwtable } -; CHECK2: ^2 = gv: (guid: {{.*}}, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) +; CHECK2: ^2 = gv: (guid: {{.*}}, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0)))) diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll index c1b09c5b42fa9..72550fa4d6f0b 100644 --- a/llvm/test/ThinLTO/X86/import_callee_declaration.ll +++ b/llvm/test/ThinLTO/X86/import_callee_declaration.ll @@ -67,12 +67,12 @@ ; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS ; ; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) -; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), insts: 8, {{.*}}))) +; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) ; When alias is imported as a copy of the aliasee, but the aliasee is not being ; imported by itself, the aliasee should be null. -; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), aliasee: null))) -; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), insts: 8, {{.*}}))) -; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration, noRenameOnPromotion: 0), aliasee: [[LARGEINDIRECT]]))) +; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null))) +; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: [[LARGEINDIRECT]]))) ; RUN: opt -passes=function-import -import-all-index -summary-file=main.bc.thinlto.bc main.bc -o main-after-import.bc ; RUN: llvm-dis -o - main-after-import.bc | FileCheck %s --check-prefix=MAIN-IMPORT diff --git a/llvm/test/ThinLTO/X86/load-store-caching.ll b/llvm/test/ThinLTO/X86/load-store-caching.ll index 85156881f0429..b25308bf17616 100644 --- a/llvm/test/ThinLTO/X86/load-store-caching.ll +++ b/llvm/test/ThinLTO/X86/load-store-caching.ll @@ -22,5 +22,5 @@ entry: } ; CHECK: ^0 = module: -; CHECK-NEXT: ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid = -; CHECK-NEXT: ^2 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition, noRenameOnPromotion: 0), insts: 3, refs: (^1)))) ; guid = +; CHECK-NEXT: ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid = +; CHECK-NEXT: ^2 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 3, refs: (^1)))) ; guid = diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll b/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll deleted file mode 100644 index f9d26e7829fd9..0000000000000 --- a/llvm/test/ThinLTO/X86/reduce-promotion-devirt.ll +++ /dev/null @@ -1,99 +0,0 @@ -; Test that renaming is still performed even when we try to avoid always renaming -; on promotion. The devirtualization promotes an internal virtual target to a -; uniqued hidden symbol from a static function, and later on the static funciton -; is promoted to the same hidden symbol. - -; Set up -; RUN: rm -rf %t -; RUN: mkdir -p %t -; RUN: split-file %s %t - -; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc -; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc - -; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ -; RUN: --whole-program-visibility-enabled-in-lto=true \ -; RUN: -always-rename-promoted-locals=false \ -; RUN: -save-temps -o %t/lto-out \ -; RUN: -r %t/a.bc,test,px \ -; RUN: -r %t/b.bc,_ZN1B1fEi,p \ -; RUN: -r %t/b.bc,test2,px \ -; RUN: -r %t/b.bc,_ZTV1B,px - -; RUN: llvm-nm %t/lto-out.1 | FileCheck %s --check-prefix=NM-INDEX1 -; RUN: llvm-nm %t/lto-out.2 | FileCheck %s --check-prefix=NM-INDEX2 - -; NM-INDEX1: U _ZN1A1nEi.llvm. -; NM-INDEX2-NOT: U _ZN1A1nEi -; NM-INDEX2: T _ZN1A1nEi.llvm. -; NM-INDEX2-NOT: U _ZN1A1nEi - -; RUN: llvm-dis %t/lto-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT-INDEX1 -; RUN: llvm-dis %t/lto-out.2.4.opt.bc -o - | FileCheck %s --check-prefix=OPT-INDEX2 - -; OPT-INDEX1: %call = tail call i32 @_ZN1A1nEi.llvm. -; OPT-INDEX1: declare void @_ZN1A1nEi.llvm. - -; OPT-INDEX2: ptr @_ZN1A1nEi.llvm. -; OPT-INDEX2: define hidden i32 @_ZN1A1nEi.llvm. -; OPT-INDEX2: tail call i32 @_ZN1A1nEi.llvm. - -;--- a.ll -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-linux-gnu" - -%struct.A = type { ptr } - -define i32 @test(ptr %obj, i32 %a) { -entry: - %vtable = load ptr, ptr %obj - %p = call i1 @llvm.type.test(ptr %vtable, metadata !"_ZTS1A") - call void @llvm.assume(i1 %p) - %fptrptr = getelementptr ptr, ptr %vtable, i32 1 - %fptr1 = load ptr, ptr %fptrptr, align 8 - - ; the call was devirtualized. - %call = tail call i32 %fptr1(ptr nonnull %obj, i32 %a) - ret i32 %call -} - -declare i1 @llvm.type.test(ptr, metadata) -declare void @llvm.assume(i1) - -;--- b.ll -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-linux-gnu" - -%struct.A = type { ptr } -%struct.B = type { %struct.A } - -@_ZTV1B = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr poison, ptr @_ZN1B1fEi, ptr @_ZN1A1nEi] }, !type !0, !type !1 - -define i32 @_ZN1B1fEi(ptr %this, i32 %a) #0 { - ret i32 0; -} - -define internal i32 @_ZN1A1nEi(ptr %this, i32 %a) #0 { - ret i32 0; -} - -define i32 @test2(ptr %obj, i32 %a) { -entry: - %vtable2 = load ptr, ptr %obj - %p2 = call i1 @llvm.type.test(ptr %vtable2, metadata !"_ZTS1B") - call void @llvm.assume(i1 %p2) - - %fptrptr = getelementptr ptr, ptr %vtable2, i32 1 - %fptr33 = load ptr, ptr %fptrptr, align 8 - - %call4 = tail call i32 %fptr33(ptr nonnull %obj, i32 %a) - ret i32 %call4 -} - -attributes #0 = { noinline optnone } - -declare i1 @llvm.type.test(ptr, metadata) -declare void @llvm.assume(i1) - -!0 = !{i64 16, !"_ZTS1A"} -!1 = !{i64 16, !"_ZTS1B"} diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll deleted file mode 100644 index cc7596c2fb385..0000000000000 --- a/llvm/test/ThinLTO/X86/reduce-promotion-same-file-local-name.ll +++ /dev/null @@ -1,46 +0,0 @@ -; Two same-name same-file static functions, meaning that they have the same GUID, -; are in both modules respectively. -; This is to test the support for avoiding always renaming, and ensure that -; one copy is still renamed despite the GUID conflict. - -; RUN: opt -thinlto-bc %s -o %t1.bc -; RUN: opt -thinlto-bc %p/Inputs/reduce-promotion-same-file-local-name.ll -o %t2.bc -; -; RUN: llvm-lto2 run %t1.bc %t2.bc \ -; RUN: --whole-program-visibility-enabled-in-lto=true \ -; RUN: -always-rename-promoted-locals=false \ -; RUN: -save-temps -o %t3 \ -; RUN: -r %t1.bc,m1,px \ -; RUN: -r %t2.bc,m2,p \ -; RUN: -r %t1.bc,m2,x -; RUN: llvm-dis %t3.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 -; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 -; -; IMPORT1: define dso_local i32 @m1( -; IMPORT1: tail call fastcc i32 @foo.{{[0-9]+}}( -; IMPORT1: define available_externally i32 @m2( -; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( -; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( - -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-pc-linux-gnu" - -source_filename = "foo.c" - -define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { - %2 = shl nsw i32 %0, 1 - %3 = tail call fastcc i32 @foo(i32 noundef %2) - %4 = tail call i32 @m2(i32 noundef %0) - %5 = add nsw i32 %4, %3 - ret i32 %5 -} - -define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { - %2 = add nsw i32 %0, 5 - %3 = sdiv i32 %2, %0 - ret i32 %3 -} - -declare i32 @m2(i32 noundef) local_unnamed_addr - -attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll b/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll deleted file mode 100644 index 9ddcae6e7bc6d..0000000000000 --- a/llvm/test/ThinLTO/X86/reduce-promotion-same-local-name.ll +++ /dev/null @@ -1,69 +0,0 @@ -; This is to test the support for avoiding always renaming, and ensure that -; one copy is still renamed despite having different GUIDs. - -; Set up -; RUN: rm -rf %t -; RUN: mkdir -p %t -; RUN: split-file %s %t - -; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc -; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc -; -; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ -; RUN: --whole-program-visibility-enabled-in-lto=true \ -; RUN: -always-rename-promoted-locals=false \ -; RUN: -save-temps -o %t/lto-out \ -; RUN: -r %t/a.bc,m1,px \ -; RUN: -r %t/b.bc,m2,p \ -; RUN: -r %t/a.bc,m2,x -; RUN: llvm-dis %t/lto-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 -; RUN: llvm-dis %t/lto-out.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 -; -; IMPORT1: define dso_local i32 @m1( -; IMPORT1: tail call fastcc i32 @foo.{{[0-9]+}}( -; IMPORT1: define available_externally i32 @m2( -; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( -; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( - -;--- a.ll -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-pc-linux-gnu" - -define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { - %2 = shl nsw i32 %0, 1 - %3 = tail call fastcc i32 @foo(i32 noundef %2) - %4 = tail call i32 @m2(i32 noundef %0) - %5 = add nsw i32 %4, %3 - ret i32 %5 -} - -define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { - %2 = add nsw i32 %0, 5 - %3 = sdiv i32 %2, %0 - ret i32 %3 -} - -declare i32 @m2(i32 noundef) local_unnamed_addr - -attributes #1 = { noinline } - -;--- b.ll -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-pc-linux-gnu" - -; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable -define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { - %2 = tail call fastcc i32 @foo(i32 noundef %0) - %3 = shl nsw i32 %0, 1 - %4 = tail call fastcc i32 @foo(i32 noundef %3) - %5 = add nsw i32 %4, %2 - ret i32 %5 -} - -define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { - %2 = add nsw i32 %0, 5 - %3 = sdiv i32 %2, %0 - ret i32 %3 -} - -attributes #1 = { noinline } diff --git a/llvm/test/ThinLTO/X86/reduce-promotion.ll b/llvm/test/ThinLTO/X86/reduce-promotion.ll deleted file mode 100644 index e8900c365675b..0000000000000 --- a/llvm/test/ThinLTO/X86/reduce-promotion.ll +++ /dev/null @@ -1,56 +0,0 @@ -; Test a simple cross module promotion where the suffix '.llvm.<...>' is not needed -; because when avoiding always renaming, we should detect that there is a single -; version of local foo which doesn't need renaming. - -; Set up -; RUN: rm -rf %t -; RUN: mkdir -p %t -; RUN: split-file %s %t - -; RUN: opt -thinlto-bc %t/a.ll -o %t/a.bc -; RUN: opt -thinlto-bc %t/b.ll -o %t/b.bc -; -; RUN: llvm-lto2 run %t/a.bc %t/b.bc \ -; RUN: --whole-program-visibility-enabled-in-lto=true \ -; RUN: -always-rename-promoted-locals=false \ -; RUN: -save-temps -o %t/lto-out \ -; RUN: -r %t/a.bc,m1,px \ -; RUN: -r %t/b.bc,m2,p \ -; RUN: -r %t/a.bc,m2,x -; RUN: llvm-dis %t/lto-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT1 -; RUN: llvm-dis %t/lto-out.2.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT2 -; -; IMPORT1: define available_externally i32 @m2( -; IMPORT1-NEXT: %2 = tail call fastcc i32 @foo( -; IMPORT2: define hidden fastcc range(i32 -2147483647, -2147483648) i32 @foo( - -;--- a.ll -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-pc-linux-gnu" - -define dso_local i32 @m1(i32 noundef %0) local_unnamed_addr { - %2 = tail call i32 @m2(i32 noundef %0) - ret i32 %2 -} - -declare i32 @m2(i32 noundef) local_unnamed_addr - -;--- b.ll -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-pc-linux-gnu" - -define dso_local i32 @m2(i32 noundef %0) local_unnamed_addr { - %2 = tail call fastcc i32 @foo(i32 noundef %0) - %3 = shl nsw i32 %0, 1 - %4 = tail call fastcc i32 @foo(i32 noundef %3) - %5 = add nsw i32 %4, %2 - ret i32 %5 -} - -define internal fastcc range(i32 -2147483647, -2147483648) i32 @foo(i32 noundef %0) unnamed_addr #1 { - %2 = add nsw i32 %0, 5 - %3 = sdiv i32 %2, %0 - ret i32 %3 -} - -attributes #1 = { noinline } diff --git a/llvm/test/Transforms/LowerTypeTests/import-unsat.ll b/llvm/test/Transforms/LowerTypeTests/import-unsat.ll index 578e7db70675c..f766c2d324163 100644 --- a/llvm/test/Transforms/LowerTypeTests/import-unsat.ll +++ b/llvm/test/Transforms/LowerTypeTests/import-unsat.ll @@ -11,7 +11,6 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 0 -; SUMMARY-NEXT: RenameOnPromotion: false ; SUMMARY-NEXT: TypeTests: [ 123 ] ; SUMMARY-NEXT: TypeIdMap: ; SUMMARY-NEXT: typeid1: diff --git a/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml b/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml index 97688cc6d8fc8..22533ed636a50 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml +++ b/llvm/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml @@ -26,7 +26,6 @@ GlobalValueMap: 43: - Live: true ImportType : 1 - NoRenameOnPromotion: true TypeIdMap: typeid1: WPDRes: diff --git a/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll b/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll index 779ca8f690288..2c33059b6e126 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll +++ b/llvm/test/Transforms/WholeProgramDevirt/import-indir.ll @@ -11,7 +11,6 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 0 -; SUMMARY-NEXT: NoRenameOnPromotion: false ; SUMMARY-NEXT: TypeTestAssumeVCalls: ; SUMMARY-NEXT: - GUID: 123 ; SUMMARY-NEXT: Offset: 0 @@ -40,7 +39,6 @@ ; SUMMARY-NEXT: Local: false ; SUMMARY-NEXT: CanAutoHide: false ; SUMMARY-NEXT: ImportType: 1 -; SUMMARY-NEXT: NoRenameOnPromotion: true ; SUMMARY-NEXT: TypeIdMap: ; SUMMARY-NEXT: typeid1: ; SUMMARY-NEXT: TTRes: From 179c25eaefe651f815f4a32328d8e51dfcda1d34 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Fri, 27 Feb 2026 10:06:46 -0800 Subject: [PATCH 17/58] [MTE] [HWASan] support more complicated lifetimes This allows us to support more lifetimes, and also gets rid of the quadratic call to isPotentiallyReachable. Reviewers: pcc, usama54321 Reviewed By: pcc Pull Request: https://github.com/llvm/llvm-project/pull/182425 --- .../Transforms/Utils/MemoryTaggingSupport.h | 14 +- .../Target/AArch64/AArch64StackTagging.cpp | 9 +- .../Instrumentation/HWAddressSanitizer.cpp | 2 +- .../Transforms/Utils/MemoryTaggingSupport.cpp | 77 ++-- llvm/test/CodeGen/AArch64/stack-tagging.ll | 12 +- .../HWAddressSanitizer/use-after-scope.ll | 417 +++++++++++++++--- 6 files changed, 410 insertions(+), 121 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h index 0491287810941..69a4f6548317e 100644 --- a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h +++ b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h @@ -30,11 +30,19 @@ class AllocaInst; class Instruction; namespace memtag { struct AllocaInfo { + struct BBInfo { + Intrinsic::ID First = Intrinsic::not_intrinsic; + Intrinsic::ID Last = Intrinsic::not_intrinsic; + // This BB calls lifetime.end twice without a start inbetween. + // TODO: handle this case smarter than just throwing out lifetime + // annotations completely. + bool DoubleEnd = false; + }; AllocaInst *AI; SmallVector LifetimeStart; SmallVector LifetimeEnd; SmallVector DbgVariableRecords; - MapVector LastBBLifetime; + MapVector BBInfos; }; // For an alloca valid between lifetime markers Start and Ends, call the @@ -49,8 +57,8 @@ bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const SmallVectorImpl &RetVec, llvm::function_ref Callback); -bool isStandardLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, - const LoopInfo *LI, size_t MaxLifetimes); +bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, + const LoopInfo *LI); Instruction *getUntagLocationIfFunctionExit(Instruction &Inst); diff --git a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp index 3e099e8216266..80ff850be269f 100644 --- a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp +++ b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp @@ -68,12 +68,6 @@ static cl::opt ClMergeInitSizeLimit("stack-tagging-merge-init-size-limit", cl::init(272), cl::Hidden); -static cl::opt ClMaxLifetimes( - "stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), - cl::ReallyHidden, - cl::desc("How many lifetime ends to handle for a single alloca."), - cl::Optional); - // Mode for selecting how to insert frame record info into the stack ring // buffer. enum StackTaggingRecordStackHistoryMode { @@ -598,8 +592,7 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) { // function return. Work around this by always untagging at every return // statement if return_twice functions are called. bool StandardLifetime = - !SInfo.CallsReturnTwice && - memtag::isStandardLifetime(Info, DT, LI, ClMaxLifetimes); + !SInfo.CallsReturnTwice && memtag::isSupportedLifetime(Info, DT, LI); if (StandardLifetime) { uint64_t Size = *Info.AI->getAllocationSize(*DL); Size = alignTo(Size, kTagGranuleSize); diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index fcad2705cf584..d57e2ee0839e3 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -1526,7 +1526,7 @@ void HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo, // function return. Work around this by always untagging at every return // statement if return_twice functions are called. if (DetectUseAfterScope && !SInfo.CallsReturnTwice && - memtag::isStandardLifetime(Info, &DT, &LI, ClMaxLifetimes)) { + memtag::isSupportedLifetime(Info, &DT, &LI)) { TagStarts(); if (!memtag::forAllReachableExits(DT, PDT, LI, Info, SInfo.RetVec, TagEnd)) { diff --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp index e9def70d24d9e..b13e7353674bf 100644 --- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp +++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp @@ -21,29 +21,13 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" +#include namespace llvm { namespace memtag { -namespace { -bool maybeReachableFromEachOther(const SmallVectorImpl &Insts, - const DominatorTree *DT, const LoopInfo *LI, - size_t MaxLifetimes) { - // If we have too many lifetime ends, give up, as the algorithm below is N^2. - if (Insts.size() > MaxLifetimes) - return true; - for (size_t I = 0; I < Insts.size(); ++I) { - for (size_t J = 0; J < Insts.size(); ++J) { - if (I == J) - continue; - if (isPotentiallyReachable(Insts[I], Insts[J], nullptr, DT, LI)) - return true; - } - } - return false; -} -} // namespace bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, @@ -56,8 +40,8 @@ bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, } SmallPtrSet EndBlocks; SmallVector StartBlocks; - for (const auto &[BB, ID] : AInfo.LastBBLifetime) { - if (ID == Intrinsic::lifetime_end) + for (const auto &[BB, BBInfo] : AInfo.BBInfos) { + if (BBInfo.Last == Intrinsic::lifetime_end) EndBlocks.insert(BB); else StartBlocks.push_back(BB); @@ -85,16 +69,28 @@ bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, return !UncoveredRets; } -bool isStandardLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, - const LoopInfo *LI, size_t MaxLifetimes) { - // An alloca that has exactly one start and end in every possible execution. - // If it has multiple ends, they have to be unreachable from each other, so - // at most one of them is actually used for each execution of the function. - return AInfo.LifetimeStart.size() > 0 && - (AInfo.LifetimeEnd.size() == 1 || - (AInfo.LifetimeEnd.size() > 0 && - !maybeReachableFromEachOther(AInfo.LifetimeEnd, DT, LI, - MaxLifetimes))); +bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, + const LoopInfo *LI) { + if (AInfo.LifetimeStart.empty()) + return false; + SmallVector LastEndBlocks; + SmallPtrSet FirstEndBlocks; + SmallPtrSet StartBlocks; + if (any_of(AInfo.BBInfos, [&](const auto &It) { + const auto &[BB, BBI] = It; + if (BBI.Last == Intrinsic::lifetime_end) + LastEndBlocks.append(succ_begin(BB), succ_end(BB)); + else + StartBlocks.insert(BB); + if (BBI.First == Intrinsic::lifetime_end) + FirstEndBlocks.insert(BB); + return BBI.DoubleEnd; + })) + return false; + if (LastEndBlocks.empty() || FirstEndBlocks.empty()) + return true; + return !isManyPotentiallyReachableFromMany(LastEndBlocks, FirstEndBlocks, + &StartBlocks, DT, LI); } Instruction *getUntagLocationIfFunctionExit(Instruction &Inst) { @@ -157,12 +153,21 @@ void StackInfoBuilder::visit(OptimizationRemarkEmitter &ORE, if (!AI || getAllocaInterestingness(*AI) != AllocaInterestingness::kInteresting) return; - if (II->getIntrinsicID() == Intrinsic::lifetime_start) - Info.AllocasToInstrument[AI].LifetimeStart.push_back(II); - else - Info.AllocasToInstrument[AI].LifetimeEnd.push_back(II); - Info.AllocasToInstrument[AI].LastBBLifetime[II->getParent()] = - II->getIntrinsicID(); + auto &AInfo = Info.AllocasToInstrument[AI]; + auto &BBInfo = AInfo.BBInfos[II->getParent()]; + + if (II->getIntrinsicID() == Intrinsic::lifetime_start) { + AInfo.LifetimeStart.push_back(II); + } else { + AInfo.LifetimeEnd.push_back(II); + if (BBInfo.Last == Intrinsic::lifetime_end) + BBInfo.DoubleEnd = true; + } + + BBInfo.Last = II->getIntrinsicID(); + if (BBInfo.First == Intrinsic::not_intrinsic) + BBInfo.First = II->getIntrinsicID(); + return; } diff --git a/llvm/test/CodeGen/AArch64/stack-tagging.ll b/llvm/test/CodeGen/AArch64/stack-tagging.ll index 5d73c7ba968aa..3e36a348bed35 100644 --- a/llvm/test/CodeGen/AArch64/stack-tagging.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging.ll @@ -94,8 +94,7 @@ if.end: ; CHECK: ret void -; Spooked by the multiple lifetime ranges, StackTagging remove all of them and sets tags on entry and exit. -define void @BadScope(i32 %b) sanitize_memtag { +define void @DoubleScope(i32 %b) sanitize_memtag { entry: %x = alloca i32, align 4 %tobool = icmp eq i32 %b, 0 @@ -115,14 +114,15 @@ if.end: ret void } -; CHECK-LABEL: define void @BadScope( -; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) +; CHECK-LABEL: define void @DoubleScope( ; CHECK: br i1 +; CHECK: call void @llvm.aarch64.settag( ; CHECK: call void @use8(ptr +; CHECK: call void @llvm.aarch64.settag( +; CHECK: call void @llvm.aarch64.settag( ; CHECK-NEXT: call void @use8(ptr +; CHECK: call void @llvm.aarch64.settag( ; CHECK: br label -; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) -; CHECK-NEXT: ret void define void @DynamicAllocas(i32 %cnt) sanitize_memtag { entry: diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll index 35e15ed7c8083..b29d069db1b3c 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll @@ -586,20 +586,20 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; X86-SCOPE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP6]], 57 ; X86-SCOPE-NEXT: [[TMP10:%.*]] = or i64 [[TMP8]], [[TMP9]] ; X86-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP10]] to ptr -; X86-SCOPE-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP6]] to i8 -; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP11]], i64 16) +; X86-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: [[TMP16:%.*]] = trunc i64 [[TMP6]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP16]], i64 16) ; X86-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) ; X86-SCOPE-NEXT: [[TMP12:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP12]], i64 16) +; X86-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]]) +; X86-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: [[TMP14:%.*]] = trunc i64 [[TMP6]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP14]], i64 16) ; X86-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) -; X86-SCOPE-NEXT: [[TMP13:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP13]], i64 16) ; X86-SCOPE-NEXT: [[TMP15:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP15]], i64 16) +; X86-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: ret i32 0 ; ; X86-NOSCOPE-LABEL: @multiple_lifetimes( @@ -654,12 +654,7 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 ; AARCH64-SCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] ; AARCH64-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr -; AARCH64-SCOPE-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8 -; AARCH64-SCOPE-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SCOPE-NEXT: [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935 -; AARCH64-SCOPE-NEXT: [[TMP28:%.*]] = lshr i64 [[TMP27]], 4 -; AARCH64-SCOPE-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]] -; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP29]], i8 [[TMP25]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) ; AARCH64-SCOPE-NEXT: [[TMP50:%.*]] = trunc i64 [[TMP20]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP51:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP52:%.*]] = and i64 [[TMP51]], 72057594037927935 @@ -673,6 +668,8 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SCOPE-NEXT: [[TMP33:%.*]] = lshr i64 [[TMP32]], 4 ; AARCH64-SCOPE-NEXT: [[TMP34:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP33]] ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP34]], i8 [[TMP30]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) ; AARCH64-SCOPE-NEXT: [[TMP40:%.*]] = trunc i64 [[TMP20]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP41:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP42:%.*]] = and i64 [[TMP41]], 72057594037927935 @@ -680,18 +677,13 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SCOPE-NEXT: [[TMP44:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP43]] ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP44]], i8 [[TMP40]], i64 1, i1 false) ; AARCH64-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) -; AARCH64-SCOPE-NEXT: [[TMP35:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; AARCH64-SCOPE-NEXT: [[TMP36:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SCOPE-NEXT: [[TMP37:%.*]] = and i64 [[TMP36]], 72057594037927935 -; AARCH64-SCOPE-NEXT: [[TMP38:%.*]] = lshr i64 [[TMP37]], 4 -; AARCH64-SCOPE-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP38]] -; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP39]], i8 [[TMP35]], i64 1, i1 false) ; AARCH64-SCOPE-NEXT: [[TMP45:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP46:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP47:%.*]] = and i64 [[TMP46]], 72057594037927935 ; AARCH64-SCOPE-NEXT: [[TMP48:%.*]] = lshr i64 [[TMP47]], 4 ; AARCH64-SCOPE-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP48]] ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP49]], i8 [[TMP45]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) ; AARCH64-SCOPE-NEXT: ret i32 0 ; ; AARCH64-NOSCOPE-LABEL: @multiple_lifetimes( @@ -770,15 +762,7 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SHORT-SCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] ; AARCH64-SHORT-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr -; AARCH64-SHORT-SCOPE-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP28:%.*]] = lshr i64 [[TMP27]], 4 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]] -; AARCH64-SHORT-SCOPE-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[TMP29]], i32 0 -; AARCH64-SHORT-SCOPE-NEXT: store i8 1, ptr [[TMP30]], align 1 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 -; AARCH64-SHORT-SCOPE-NEXT: store i8 [[TMP25]], ptr [[TMP31]], align 1 +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) ; AARCH64-SHORT-SCOPE-NEXT: [[TMP54:%.*]] = trunc i64 [[TMP20]] to i8 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP55:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP56:%.*]] = and i64 [[TMP55]], 72057594037927935 @@ -795,6 +779,8 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SHORT-SCOPE-NEXT: [[TMP47:%.*]] = lshr i64 [[TMP46]], 4 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP48:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP47]] ; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP48]], i8 [[TMP44]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) ; AARCH64-SHORT-SCOPE-NEXT: [[TMP37:%.*]] = trunc i64 [[TMP20]] to i8 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP38:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP39:%.*]] = and i64 [[TMP38]], 72057594037927935 @@ -805,18 +791,13 @@ define dso_local i32 @multiple_lifetimes() local_unnamed_addr sanitize_hwaddress ; AARCH64-SHORT-SCOPE-NEXT: [[TMP43:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 ; AARCH64-SHORT-SCOPE-NEXT: store i8 [[TMP37]], ptr [[TMP43]], align 1 ; AARCH64-SHORT-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) -; AARCH64-SHORT-SCOPE-NEXT: [[TMP32:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP33:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP34:%.*]] = and i64 [[TMP33]], 72057594037927935 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP35:%.*]] = lshr i64 [[TMP34]], 4 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP36:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP35]] -; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP36]], i8 [[TMP32]], i64 1, i1 false) ; AARCH64-SHORT-SCOPE-NEXT: [[TMP49:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP50:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP51:%.*]] = and i64 [[TMP50]], 72057594037927935 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP52:%.*]] = lshr i64 [[TMP51]], 4 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP53:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP52]] ; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP53]], i8 [[TMP49]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) ; AARCH64-SHORT-SCOPE-NEXT: ret i32 0 ; ; AARCH64-SHORT-NOSCOPE-LABEL: @multiple_lifetimes( @@ -2836,24 +2817,24 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { ; X86-SCOPE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP6]], 57 ; X86-SCOPE-NEXT: [[TMP10:%.*]] = or i64 [[TMP8]], [[TMP9]] ; X86-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP10]] to ptr -; X86-SCOPE-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP6]] to i8 -; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP11]], i64 16) ; X86-SCOPE-NEXT: br label [[TMP12:%.*]] -; X86-SCOPE: 12: +; X86-SCOPE: 11: +; X86-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: [[TMP13:%.*]] = trunc i64 [[TMP6]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP13]], i64 16) ; X86-SCOPE-NEXT: [[TMP14:%.*]] = tail call i1 (...) @cond() ; X86-SCOPE-NEXT: [[TMP15:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP15]], i64 16) +; X86-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: br i1 [[TMP14]], label [[TMP16:%.*]], label [[TMP12]] -; X86-SCOPE: 16: +; X86-SCOPE: 15: +; X86-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: [[TMP17:%.*]] = trunc i64 [[TMP6]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP17]], i64 16) ; X86-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) -; X86-SCOPE-NEXT: [[TMP18:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP18]], i64 16) ; X86-SCOPE-NEXT: [[TMP19:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP19]], i64 16) +; X86-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]]) ; X86-SCOPE-NEXT: ret i32 0 ; ; X86-NOSCOPE-LABEL: @double_lifetime( @@ -2912,6 +2893,324 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { ; AARCH64-SCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 ; AARCH64-SCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] ; AARCH64-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr +; AARCH64-SCOPE-NEXT: br label [[TMP30:%.*]] +; AARCH64-SCOPE: 25: +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) +; AARCH64-SCOPE-NEXT: [[TMP31:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SCOPE-NEXT: [[TMP32:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP33:%.*]] = and i64 [[TMP32]], 72057594037927935 +; AARCH64-SCOPE-NEXT: [[TMP34:%.*]] = lshr i64 [[TMP33]], 4 +; AARCH64-SCOPE-NEXT: [[TMP35:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP34]] +; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP35]], i8 [[TMP31]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: [[TMP36:%.*]] = tail call i1 (...) @cond() +; AARCH64-SCOPE-NEXT: [[TMP37:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SCOPE-NEXT: [[TMP38:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP39:%.*]] = and i64 [[TMP38]], 72057594037927935 +; AARCH64-SCOPE-NEXT: [[TMP40:%.*]] = lshr i64 [[TMP39]], 4 +; AARCH64-SCOPE-NEXT: [[TMP41:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP40]] +; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 [[TMP37]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SCOPE-NEXT: br i1 [[TMP36]], label [[TMP42:%.*]], label [[TMP30]] +; AARCH64-SCOPE: 37: +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) +; AARCH64-SCOPE-NEXT: [[TMP43:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SCOPE-NEXT: [[TMP44:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP45:%.*]] = and i64 [[TMP44]], 72057594037927935 +; AARCH64-SCOPE-NEXT: [[TMP46:%.*]] = lshr i64 [[TMP45]], 4 +; AARCH64-SCOPE-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP46]] +; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP47]], i8 [[TMP43]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-SCOPE-NEXT: [[TMP53:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SCOPE-NEXT: [[TMP54:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP55:%.*]] = and i64 [[TMP54]], 72057594037927935 +; AARCH64-SCOPE-NEXT: [[TMP56:%.*]] = lshr i64 [[TMP55]], 4 +; AARCH64-SCOPE-NEXT: [[TMP57:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP56]] +; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP57]], i8 [[TMP53]], i64 1, i1 false) +; AARCH64-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SCOPE-NEXT: ret i32 0 +; +; AARCH64-NOSCOPE-LABEL: @double_lifetime( +; AARCH64-NOSCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() +; AARCH64-NOSCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 +; AARCH64-NOSCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 +; AARCH64-NOSCOPE-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3 +; AARCH64-NOSCOPE-NEXT: [[TMP5:%.*]] = call i64 @llvm.read_register.i64(metadata [[META2]]) +; AARCH64-NOSCOPE-NEXT: [[TMP6:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; AARCH64-NOSCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64 +; AARCH64-NOSCOPE-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 44 +; AARCH64-NOSCOPE-NEXT: [[TMP9:%.*]] = or i64 [[TMP5]], [[TMP8]] +; AARCH64-NOSCOPE-NEXT: [[TMP10:%.*]] = inttoptr i64 [[TMP3]] to ptr +; AARCH64-NOSCOPE-NEXT: store i64 [[TMP9]], ptr [[TMP10]], align 8 +; AARCH64-NOSCOPE-NEXT: [[TMP11:%.*]] = ashr i64 [[TMP3]], 56 +; AARCH64-NOSCOPE-NEXT: [[TMP12:%.*]] = shl nuw nsw i64 [[TMP11]], 12 +; AARCH64-NOSCOPE-NEXT: [[TMP13:%.*]] = xor i64 [[TMP12]], -1 +; AARCH64-NOSCOPE-NEXT: [[TMP14:%.*]] = add i64 [[TMP3]], 8 +; AARCH64-NOSCOPE-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], [[TMP13]] +; AARCH64-NOSCOPE-NEXT: store i64 [[TMP15]], ptr [[TMP2]], align 8 +; AARCH64-NOSCOPE-NEXT: [[TMP16:%.*]] = or i64 [[TMP3]], 4294967295 +; AARCH64-NOSCOPE-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP16]], 1 +; AARCH64-NOSCOPE-NEXT: [[TMP17:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; AARCH64-NOSCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = lshr i64 [[TMP7]], 56 +; AARCH64-NOSCOPE-NEXT: [[TMP18:%.*]] = alloca { i8, [15 x i8] }, align 16 +; AARCH64-NOSCOPE-NEXT: [[TMP19:%.*]] = call i8 @__hwasan_generate_tag() +; AARCH64-NOSCOPE-NEXT: [[TMP20:%.*]] = zext i8 [[TMP19]] to i64 +; AARCH64-NOSCOPE-NEXT: [[TMP21:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-NOSCOPE-NEXT: [[TMP22:%.*]] = and i64 [[TMP21]], 72057594037927935 +; AARCH64-NOSCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 +; AARCH64-NOSCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] +; AARCH64-NOSCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr +; AARCH64-NOSCOPE-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-NOSCOPE-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-NOSCOPE-NEXT: [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935 +; AARCH64-NOSCOPE-NEXT: [[TMP28:%.*]] = lshr i64 [[TMP27]], 4 +; AARCH64-NOSCOPE-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]] +; AARCH64-NOSCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP29]], i8 [[TMP25]], i64 1, i1 false) +; AARCH64-NOSCOPE-NEXT: br label [[TMP30:%.*]] +; AARCH64-NOSCOPE: 30: +; AARCH64-NOSCOPE-NEXT: [[TMP31:%.*]] = tail call i1 (...) @cond() +; AARCH64-NOSCOPE-NEXT: br i1 [[TMP31]], label [[TMP32:%.*]], label [[TMP30]] +; AARCH64-NOSCOPE: 32: +; AARCH64-NOSCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-NOSCOPE-NEXT: [[TMP33:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-NOSCOPE-NEXT: [[TMP34:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-NOSCOPE-NEXT: [[TMP35:%.*]] = and i64 [[TMP34]], 72057594037927935 +; AARCH64-NOSCOPE-NEXT: [[TMP36:%.*]] = lshr i64 [[TMP35]], 4 +; AARCH64-NOSCOPE-NEXT: [[TMP37:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP36]] +; AARCH64-NOSCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP37]], i8 [[TMP33]], i64 1, i1 false) +; AARCH64-NOSCOPE-NEXT: ret i32 0 +; +; AARCH64-SHORT-SCOPE-LABEL: @double_lifetime( +; AARCH64-SHORT-SCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() +; AARCH64-SHORT-SCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP5:%.*]] = call i64 @llvm.read_register.i64(metadata [[META2]]) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP6:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 44 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP9:%.*]] = or i64 [[TMP5]], [[TMP8]] +; AARCH64-SHORT-SCOPE-NEXT: [[TMP10:%.*]] = inttoptr i64 [[TMP3]] to ptr +; AARCH64-SHORT-SCOPE-NEXT: store i64 [[TMP9]], ptr [[TMP10]], align 8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP11:%.*]] = ashr i64 [[TMP3]], 56 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP12:%.*]] = shl nuw nsw i64 [[TMP11]], 12 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP13:%.*]] = xor i64 [[TMP12]], -1 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP14:%.*]] = add i64 [[TMP3]], 8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], [[TMP13]] +; AARCH64-SHORT-SCOPE-NEXT: store i64 [[TMP15]], ptr [[TMP2]], align 8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP16:%.*]] = or i64 [[TMP3]], 4294967295 +; AARCH64-SHORT-SCOPE-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP16]], 1 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP17:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; AARCH64-SHORT-SCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = lshr i64 [[TMP7]], 56 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP18:%.*]] = alloca { i8, [15 x i8] }, align 16 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP19:%.*]] = call i8 @__hwasan_generate_tag() +; AARCH64-SHORT-SCOPE-NEXT: [[TMP20:%.*]] = zext i8 [[TMP19]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP21:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP22:%.*]] = and i64 [[TMP21]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] +; AARCH64-SHORT-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr +; AARCH64-SHORT-SCOPE-NEXT: br label [[TMP32:%.*]] +; AARCH64-SHORT-SCOPE: 25: +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP33:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP34:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP35:%.*]] = and i64 [[TMP34]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP36:%.*]] = lshr i64 [[TMP35]], 4 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP37:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP36]] +; AARCH64-SHORT-SCOPE-NEXT: [[TMP38:%.*]] = getelementptr i8, ptr [[TMP37]], i32 0 +; AARCH64-SHORT-SCOPE-NEXT: store i8 1, ptr [[TMP38]], align 1 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 +; AARCH64-SHORT-SCOPE-NEXT: store i8 [[TMP33]], ptr [[TMP39]], align 1 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP40:%.*]] = tail call i1 (...) @cond() +; AARCH64-SHORT-SCOPE-NEXT: [[TMP41:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP42:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP43:%.*]] = and i64 [[TMP42]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP44:%.*]] = lshr i64 [[TMP43]], 4 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP45:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP44]] +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP45]], i8 [[TMP41]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SHORT-SCOPE-NEXT: br i1 [[TMP40]], label [[TMP46:%.*]], label [[TMP32]] +; AARCH64-SHORT-SCOPE: 39: +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]]) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP47:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP48:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP49:%.*]] = and i64 [[TMP48]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP50:%.*]] = lshr i64 [[TMP49]], 4 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP51:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP50]] +; AARCH64-SHORT-SCOPE-NEXT: [[TMP52:%.*]] = getelementptr i8, ptr [[TMP51]], i32 0 +; AARCH64-SHORT-SCOPE-NEXT: store i8 1, ptr [[TMP52]], align 1 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP53:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 +; AARCH64-SHORT-SCOPE-NEXT: store i8 [[TMP47]], ptr [[TMP53]], align 1 +; AARCH64-SHORT-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP59:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP60:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP61:%.*]] = and i64 [[TMP60]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP62:%.*]] = lshr i64 [[TMP61]], 4 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP62]] +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP63]], i8 [[TMP59]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]]) +; AARCH64-SHORT-SCOPE-NEXT: ret i32 0 +; +; AARCH64-SHORT-NOSCOPE-LABEL: @double_lifetime( +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP5:%.*]] = call i64 @llvm.read_register.i64(metadata [[META2]]) +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP6:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 44 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP9:%.*]] = or i64 [[TMP5]], [[TMP8]] +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP10:%.*]] = inttoptr i64 [[TMP3]] to ptr +; AARCH64-SHORT-NOSCOPE-NEXT: store i64 [[TMP9]], ptr [[TMP10]], align 8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP11:%.*]] = ashr i64 [[TMP3]], 56 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP12:%.*]] = shl nuw nsw i64 [[TMP11]], 12 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP13:%.*]] = xor i64 [[TMP12]], -1 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP14:%.*]] = add i64 [[TMP3]], 8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], [[TMP13]] +; AARCH64-SHORT-NOSCOPE-NEXT: store i64 [[TMP15]], ptr [[TMP2]], align 8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP16:%.*]] = or i64 [[TMP3]], 4294967295 +; AARCH64-SHORT-NOSCOPE-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP16]], 1 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP17:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; AARCH64-SHORT-NOSCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = lshr i64 [[TMP7]], 56 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP18:%.*]] = alloca { i8, [15 x i8] }, align 16 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP19:%.*]] = call i8 @__hwasan_generate_tag() +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP20:%.*]] = zext i8 [[TMP19]] to i64 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP21:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP22:%.*]] = and i64 [[TMP21]], 72057594037927935 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] +; AARCH64-SHORT-NOSCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP28:%.*]] = lshr i64 [[TMP27]], 4 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]] +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[TMP29]], i32 0 +; AARCH64-SHORT-NOSCOPE-NEXT: store i8 1, ptr [[TMP30]], align 1 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 +; AARCH64-SHORT-NOSCOPE-NEXT: store i8 [[TMP25]], ptr [[TMP31]], align 1 +; AARCH64-SHORT-NOSCOPE-NEXT: br label [[TMP32:%.*]] +; AARCH64-SHORT-NOSCOPE: 32: +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP33:%.*]] = tail call i1 (...) @cond() +; AARCH64-SHORT-NOSCOPE-NEXT: br i1 [[TMP33]], label [[TMP34:%.*]], label [[TMP32]] +; AARCH64-SHORT-NOSCOPE: 34: +; AARCH64-SHORT-NOSCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP35:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP36:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP37:%.*]] = and i64 [[TMP36]], 72057594037927935 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP38:%.*]] = lshr i64 [[TMP37]], 4 +; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP38]] +; AARCH64-SHORT-NOSCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP39]], i8 [[TMP35]], i64 1, i1 false) +; AARCH64-SHORT-NOSCOPE-NEXT: ret i32 0 +; + %1 = alloca i8, align 1 + br label %2 + +2: ; preds = %2, %0 +; We should tag the memory after the br (in the loop). + call void @llvm.lifetime.start.p0(ptr nonnull %1) + %3 = tail call i1 (...) @cond() #2 +; We should tag the memory before the next br (before the jump back). + call void @llvm.lifetime.end.p0(ptr nonnull %1) + br i1 %3, label %4, label %2 + +4: ; preds = %2 + call void @llvm.lifetime.start.p0(ptr nonnull %1) + call void @use(ptr nonnull %1) #2 + call void @llvm.lifetime.end.p0(ptr nonnull %1) + ret i32 0 +} + +define dso_local i32 @bad_lifetime() local_unnamed_addr sanitize_hwaddress { +; X86-SCOPE-LABEL: @bad_lifetime( +; X86-SCOPE-NEXT: [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr null) +; X86-SCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; X86-SCOPE-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; X86-SCOPE-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP2]], 57 +; X86-SCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = and i64 [[TMP3]], 63 +; X86-SCOPE-NEXT: [[TMP4:%.*]] = alloca { i8, [15 x i8] }, align 16 +; X86-SCOPE-NEXT: [[TMP5:%.*]] = call i8 @__hwasan_generate_tag() +; X86-SCOPE-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i64 +; X86-SCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP4]] to i64 +; X86-SCOPE-NEXT: [[TMP8:%.*]] = and i64 [[TMP7]], -9079256848778919937 +; X86-SCOPE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP6]], 57 +; X86-SCOPE-NEXT: [[TMP10:%.*]] = or i64 [[TMP8]], [[TMP9]] +; X86-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP10]] to ptr +; X86-SCOPE-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP6]] to i8 +; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP11]], i64 16) +; X86-SCOPE-NEXT: br label [[TMP12:%.*]] +; X86-SCOPE: 12: +; X86-SCOPE-NEXT: [[TMP13:%.*]] = trunc i64 [[TMP6]] to i8 +; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP13]], i64 16) +; X86-SCOPE-NEXT: [[TMP14:%.*]] = tail call i1 (...) @cond() +; X86-SCOPE-NEXT: [[TMP15:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP15]], i64 16) +; X86-SCOPE-NEXT: br i1 [[TMP14]], label [[TMP16:%.*]], label [[TMP12]] +; X86-SCOPE: 16: +; X86-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; X86-SCOPE-NEXT: [[TMP17:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP17]], i64 16) +; X86-SCOPE-NEXT: [[TMP18:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; X86-SCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP18]], i64 16) +; X86-SCOPE-NEXT: ret i32 0 +; +; X86-NOSCOPE-LABEL: @bad_lifetime( +; X86-NOSCOPE-NEXT: [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr null) +; X86-NOSCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; X86-NOSCOPE-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; X86-NOSCOPE-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP2]], 57 +; X86-NOSCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = and i64 [[TMP3]], 63 +; X86-NOSCOPE-NEXT: [[TMP4:%.*]] = alloca { i8, [15 x i8] }, align 16 +; X86-NOSCOPE-NEXT: [[TMP5:%.*]] = call i8 @__hwasan_generate_tag() +; X86-NOSCOPE-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i64 +; X86-NOSCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP4]] to i64 +; X86-NOSCOPE-NEXT: [[TMP8:%.*]] = and i64 [[TMP7]], -9079256848778919937 +; X86-NOSCOPE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP6]], 57 +; X86-NOSCOPE-NEXT: [[TMP10:%.*]] = or i64 [[TMP8]], [[TMP9]] +; X86-NOSCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP10]] to ptr +; X86-NOSCOPE-NEXT: [[TMP11:%.*]] = trunc i64 [[TMP6]] to i8 +; X86-NOSCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP11]], i64 16) +; X86-NOSCOPE-NEXT: br label [[TMP12:%.*]] +; X86-NOSCOPE: 12: +; X86-NOSCOPE-NEXT: [[TMP13:%.*]] = tail call i1 (...) @cond() +; X86-NOSCOPE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP12]] +; X86-NOSCOPE: 14: +; X86-NOSCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; X86-NOSCOPE-NEXT: [[TMP15:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; X86-NOSCOPE-NEXT: call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP15]], i64 16) +; X86-NOSCOPE-NEXT: ret i32 0 +; +; AARCH64-SCOPE-LABEL: @bad_lifetime( +; AARCH64-SCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() +; AARCH64-SCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 +; AARCH64-SCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 +; AARCH64-SCOPE-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3 +; AARCH64-SCOPE-NEXT: [[TMP5:%.*]] = call i64 @llvm.read_register.i64(metadata [[META2]]) +; AARCH64-SCOPE-NEXT: [[TMP6:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; AARCH64-SCOPE-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 44 +; AARCH64-SCOPE-NEXT: [[TMP9:%.*]] = or i64 [[TMP5]], [[TMP8]] +; AARCH64-SCOPE-NEXT: [[TMP10:%.*]] = inttoptr i64 [[TMP3]] to ptr +; AARCH64-SCOPE-NEXT: store i64 [[TMP9]], ptr [[TMP10]], align 8 +; AARCH64-SCOPE-NEXT: [[TMP11:%.*]] = ashr i64 [[TMP3]], 56 +; AARCH64-SCOPE-NEXT: [[TMP12:%.*]] = shl nuw nsw i64 [[TMP11]], 12 +; AARCH64-SCOPE-NEXT: [[TMP13:%.*]] = xor i64 [[TMP12]], -1 +; AARCH64-SCOPE-NEXT: [[TMP14:%.*]] = add i64 [[TMP3]], 8 +; AARCH64-SCOPE-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], [[TMP13]] +; AARCH64-SCOPE-NEXT: store i64 [[TMP15]], ptr [[TMP2]], align 8 +; AARCH64-SCOPE-NEXT: [[TMP16:%.*]] = or i64 [[TMP3]], 4294967295 +; AARCH64-SCOPE-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP16]], 1 +; AARCH64-SCOPE-NEXT: [[TMP17:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; AARCH64-SCOPE-NEXT: [[HWASAN_UAR_TAG:%.*]] = lshr i64 [[TMP7]], 56 +; AARCH64-SCOPE-NEXT: [[TMP18:%.*]] = alloca { i8, [15 x i8] }, align 16 +; AARCH64-SCOPE-NEXT: [[TMP19:%.*]] = call i8 @__hwasan_generate_tag() +; AARCH64-SCOPE-NEXT: [[TMP20:%.*]] = zext i8 [[TMP19]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP21:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SCOPE-NEXT: [[TMP22:%.*]] = and i64 [[TMP21]], 72057594037927935 +; AARCH64-SCOPE-NEXT: [[TMP23:%.*]] = shl i64 [[TMP20]], 56 +; AARCH64-SCOPE-NEXT: [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]] +; AARCH64-SCOPE-NEXT: [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr ; AARCH64-SCOPE-NEXT: [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935 @@ -2935,28 +3234,22 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 [[TMP37]], i64 1, i1 false) ; AARCH64-SCOPE-NEXT: br i1 [[TMP36]], label [[TMP42:%.*]], label [[TMP30]] ; AARCH64-SCOPE: 42: -; AARCH64-SCOPE-NEXT: [[TMP43:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-SCOPE-NEXT: [[TMP43:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP44:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP45:%.*]] = and i64 [[TMP44]], 72057594037927935 ; AARCH64-SCOPE-NEXT: [[TMP46:%.*]] = lshr i64 [[TMP45]], 4 ; AARCH64-SCOPE-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP46]] ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP47]], i8 [[TMP43]], i64 1, i1 false) -; AARCH64-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) ; AARCH64-SCOPE-NEXT: [[TMP48:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; AARCH64-SCOPE-NEXT: [[TMP49:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SCOPE-NEXT: [[TMP50:%.*]] = and i64 [[TMP49]], 72057594037927935 ; AARCH64-SCOPE-NEXT: [[TMP51:%.*]] = lshr i64 [[TMP50]], 4 ; AARCH64-SCOPE-NEXT: [[TMP52:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP51]] ; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP52]], i8 [[TMP48]], i64 1, i1 false) -; AARCH64-SCOPE-NEXT: [[TMP53:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; AARCH64-SCOPE-NEXT: [[TMP54:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SCOPE-NEXT: [[TMP55:%.*]] = and i64 [[TMP54]], 72057594037927935 -; AARCH64-SCOPE-NEXT: [[TMP56:%.*]] = lshr i64 [[TMP55]], 4 -; AARCH64-SCOPE-NEXT: [[TMP57:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP56]] -; AARCH64-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP57]], i8 [[TMP53]], i64 1, i1 false) ; AARCH64-SCOPE-NEXT: ret i32 0 ; -; AARCH64-NOSCOPE-LABEL: @double_lifetime( +; AARCH64-NOSCOPE-LABEL: @bad_lifetime( ; AARCH64-NOSCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() ; AARCH64-NOSCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 ; AARCH64-NOSCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 @@ -3006,7 +3299,7 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { ; AARCH64-NOSCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP37]], i8 [[TMP33]], i64 1, i1 false) ; AARCH64-NOSCOPE-NEXT: ret i32 0 ; -; AARCH64-SHORT-SCOPE-LABEL: @double_lifetime( +; AARCH64-SHORT-SCOPE-LABEL: @bad_lifetime( ; AARCH64-SHORT-SCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() ; AARCH64-SHORT-SCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 @@ -3065,31 +3358,22 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { ; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP45]], i8 [[TMP41]], i64 1, i1 false) ; AARCH64-SHORT-SCOPE-NEXT: br i1 [[TMP40]], label [[TMP46:%.*]], label [[TMP32]] ; AARCH64-SHORT-SCOPE: 46: -; AARCH64-SHORT-SCOPE-NEXT: [[TMP47:%.*]] = trunc i64 [[TMP20]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP47:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP48:%.*]] = ptrtoint ptr [[TMP18]] to i64 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP49:%.*]] = and i64 [[TMP48]], 72057594037927935 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP50:%.*]] = lshr i64 [[TMP49]], 4 ; AARCH64-SHORT-SCOPE-NEXT: [[TMP51:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP50]] -; AARCH64-SHORT-SCOPE-NEXT: [[TMP52:%.*]] = getelementptr i8, ptr [[TMP51]], i32 0 -; AARCH64-SHORT-SCOPE-NEXT: store i8 1, ptr [[TMP52]], align 1 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP53:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15 -; AARCH64-SHORT-SCOPE-NEXT: store i8 [[TMP47]], ptr [[TMP53]], align 1 -; AARCH64-SHORT-SCOPE-NEXT: call void @use(ptr nonnull [[ALLOCA_0_HWASAN]]) -; AARCH64-SHORT-SCOPE-NEXT: [[TMP54:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP55:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP56:%.*]] = and i64 [[TMP55]], 72057594037927935 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP57:%.*]] = lshr i64 [[TMP56]], 4 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP58:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP57]] -; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP58]], i8 [[TMP54]], i64 1, i1 false) -; AARCH64-SHORT-SCOPE-NEXT: [[TMP59:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP60:%.*]] = ptrtoint ptr [[TMP18]] to i64 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP61:%.*]] = and i64 [[TMP60]], 72057594037927935 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP62:%.*]] = lshr i64 [[TMP61]], 4 -; AARCH64-SHORT-SCOPE-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP62]] -; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP63]], i8 [[TMP59]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP51]], i8 [[TMP47]], i64 1, i1 false) +; AARCH64-SHORT-SCOPE-NEXT: [[TMP52:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP53:%.*]] = ptrtoint ptr [[TMP18]] to i64 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP54:%.*]] = and i64 [[TMP53]], 72057594037927935 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP55:%.*]] = lshr i64 [[TMP54]], 4 +; AARCH64-SHORT-SCOPE-NEXT: [[TMP56:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP55]] +; AARCH64-SHORT-SCOPE-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP56]], i8 [[TMP52]], i64 1, i1 false) ; AARCH64-SHORT-SCOPE-NEXT: ret i32 0 ; -; AARCH64-SHORT-NOSCOPE-LABEL: @double_lifetime( +; AARCH64-SHORT-NOSCOPE-LABEL: @bad_lifetime( ; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0() ; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48 ; AARCH64-SHORT-NOSCOPE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8 @@ -3154,7 +3438,6 @@ define dso_local i32 @double_lifetime() local_unnamed_addr sanitize_hwaddress { br i1 %3, label %4, label %2 4: ; preds = %2 - call void @llvm.lifetime.start.p0(ptr nonnull %1) call void @use(ptr nonnull %1) #2 call void @llvm.lifetime.end.p0(ptr nonnull %1) ret i32 0 From 1269a74db9ffde19f8230edeac0ddbcafc3a4d66 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 27 Feb 2026 12:07:06 -0600 Subject: [PATCH 18/58] [bazel] Enable `parse_headers` for llvm/BUILD.bazel (#183680) Instead of excluding the whole package, push any existing parse_headers failures to individual targets. In some cases we can avoid suppressing a target by adding a few missing deps. --- .../llvm-project-overlay/llvm/BUILD.bazel | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index ca46622298f72..5ccf0194808ab 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -2,7 +2,6 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -load("@bazel_skylib//lib:selects.bzl", "selects") load("@bazel_skylib//rules:common_settings.bzl", "string_flag") load("@bazel_skylib//rules:expand_template.bzl", "expand_template") load("@bazel_skylib//rules:write_file.bzl", "write_file") @@ -19,7 +18,10 @@ load(":targets.bzl", "llvm_targets") package( default_visibility = ["//visibility:public"], - features = ["layering_check"], + features = [ + "parse_headers", + "layering_check", + ], ) licenses(["notice"]) @@ -343,6 +345,7 @@ cc_library( "BLAKE3_NO_SSE41", ], }), + features = ["-parse_headers"], includes = ["include"], linkopts = select({ ":is_windows_clang_mingw": [ @@ -466,6 +469,7 @@ cc_library( "include/llvm/IR/Value.def", ], copts = llvm_copts, + features = ["-parse_headers"], ) cc_library( @@ -510,6 +514,7 @@ cc_library( hdrs = glob(["include/llvm/DebugInfo/*.h"]), copts = llvm_copts, deps = [ + ":BinaryFormatELF", ":Object", ":Support", ], @@ -650,6 +655,7 @@ cc_library( "include/llvm/MC/*.h", ]), copts = llvm_copts, + features = ["-parse_headers"], deps = [ ":BinaryFormat", ":DebugInfoCodeView", @@ -841,6 +847,7 @@ cc_binary( ], ) + ["include/llvm/TargetParser/SubtargetFeature.h"], copts = llvm_copts, + features = ["-parse_headers"], includes = ["utils/TableGen"], stamp = 0, deps = [ @@ -1091,6 +1098,7 @@ cc_library( "include/llvm/ProfileData/InstrProfData.inc", ] + [":llvm_intrinsics_headers"], copts = llvm_copts, + features = ["-parse_headers"], textual_hdrs = glob([ "include/llvm/IR/*.def", ]), @@ -1321,6 +1329,7 @@ cc_library( ], ) + ["include/llvm-c/Analysis.h"], copts = llvm_copts + ["-ftrapping-math"], + features = ["-parse_headers"], textual_hdrs = glob([ "include/llvm/Analysis/*.def", ]), @@ -1576,6 +1585,7 @@ cc_library( "include/llvm/Transforms/Utils.h", ], copts = llvm_copts, + features = ["-parse_headers"], deps = [ ":Analysis", ":BinaryFormat", @@ -2165,6 +2175,7 @@ cc_library( ], ), copts = llvm_copts, + features = ["-parse_headers"], textual_hdrs = glob([ "include/llvm/CodeGen/**/*.def", ]), @@ -3800,7 +3811,10 @@ gentbl_cc_library( ), hdrs = ["lib/Target/" + target["name"] + "/" + target["short_name"] + ".h"], copts = llvm_copts, - features = ["-layering_check"], + features = [ + "-layering_check", + "-parse_headers", + ], strip_include_prefix = "lib/Target/" + target["name"], textual_hdrs = glob( [ @@ -3841,6 +3855,7 @@ gentbl_cc_library( allow_empty = True, ), copts = llvm_copts, + features = ["-parse_headers"], deps = [ ":BinaryFormat", ":CodeGenTypes", @@ -4095,11 +4110,13 @@ cc_library( ], ) + ["include/llvm-c/ExecutionEngine.h"], copts = llvm_copts, + features = ["-parse_headers"], deps = [ ":BinaryFormat", ":CodeGen", ":Core", ":DebugInfo", + ":DebugInfoDWARF", ":MC", ":MCDisassembler", ":Object", @@ -4152,7 +4169,9 @@ cc_library( ]), copts = llvm_copts, deps = [ + ":Analysis", ":BinaryFormat", + ":Core", ":ExecutionEngine", ":JITLinkTableGen", ":Object", @@ -4160,7 +4179,9 @@ cc_library( ":OrcShared", ":OrcTargetProcess", ":Support", + ":Target", ":TargetParser", + ":TransformUtils", ":config", ], ) @@ -4451,6 +4472,7 @@ cc_library( "include/llvm/WindowsDriver/*.h", ]), copts = llvm_copts, + features = ["-parse_headers"], deps = [ ":Option", ":Support", @@ -4764,6 +4786,7 @@ cc_binary( "tools/llubi/lib/*.cpp", "tools/llubi/lib/*.h", ]), + features = ["-parse_headers"], stamp = 0, deps = [ ":Analysis", @@ -6422,6 +6445,7 @@ cc_library( ]), hdrs = glob(["include/llvm/Testing/Support/*.h"]), copts = llvm_copts, + features = ["-layering_check"], deps = [ ":Support", ":config", From c3b3f4195219e368bd18fc1a1bab18d0dae45d8f Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Fri, 27 Feb 2026 13:07:49 -0500 Subject: [PATCH 19/58] [SystemZ] Emit external aliases required for indirect symbol handling support (#183442) This is the second of three patches aimed to support indirect symbol handling for the SystemZ backend. An external name is added for both MC sections and symbols and makes the relevant printers and writers utilize the external name when present. Furthermore, the ALIAS HLASM instruction is emitted after every XATTR instruction. Depends on https://github.com/llvm/llvm-project/pull/183441. --- llvm/include/llvm/MC/MCSectionGOFF.h | 8 +++++ llvm/include/llvm/MC/MCSymbolGOFF.h | 9 +++++ llvm/lib/MC/GOFFObjectWriter.cpp | 35 +++++++++++-------- llvm/lib/MC/MCAsmInfoGOFF.cpp | 7 ++++ .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp | 4 +++ .../MCTargetDesc/SystemZTargetStreamer.h | 17 +++++++++ 6 files changed, 65 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h index 2136148368fbd..288f9038bb65e 100644 --- a/llvm/include/llvm/MC/MCSectionGOFF.h +++ b/llvm/include/llvm/MC/MCSectionGOFF.h @@ -27,6 +27,8 @@ namespace llvm { class MCExpr; class LLVM_ABI MCSectionGOFF final : public MCSection { + StringRef ExternalName; // Alternate external name. + // Parent of this section. Implies that the parent is emitted first. MCSectionGOFF *Parent; @@ -115,6 +117,12 @@ class LLVM_ABI MCSectionGOFF final : public MCSection { bool requiresNonZeroLength() const { return RequiresNonZeroLength; } void setName(StringRef SectionName) { Name = SectionName; } + + bool hasExternalName() const { return !ExternalName.empty(); } + void setExternalName(StringRef Name) { ExternalName = Name; } + StringRef getExternalName() const { + return hasExternalName() ? ExternalName : getName(); + } }; } // end namespace llvm diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h index 449307217d531..8bbd53f824f1e 100644 --- a/llvm/include/llvm/MC/MCSymbolGOFF.h +++ b/llvm/include/llvm/MC/MCSymbolGOFF.h @@ -23,6 +23,9 @@ namespace llvm { class MCSymbolGOFF : public MCSymbol { + + StringRef ExternalName; // Alternate external name. + // Associated data area of the section. Needs to be emitted first. MCSectionGOFF *ADA = nullptr; @@ -48,6 +51,12 @@ class MCSymbolGOFF : public MCSymbol { bool isExternal() const { return IsExternal; } void setExternal(bool Value) const { IsExternal = Value; } + bool hasExternalName() const { return !ExternalName.empty(); } + void setExternalName(StringRef Name) { ExternalName = Name; } + StringRef getExternalName() const { + return hasExternalName() ? ExternalName : getName(); + } + void setHidden(bool Value = true) { modifyFlags(Value ? SF_Hidden : 0, SF_Hidden); } diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp index a619328c09fa3..9319a377ca10b 100644 --- a/llvm/lib/MC/GOFFObjectWriter.cpp +++ b/llvm/lib/MC/GOFFObjectWriter.cpp @@ -315,13 +315,13 @@ GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) { if (Section.isSD()) { - GOFFSymbol SD(Section.getName(), Section.getOrdinal(), + GOFFSymbol SD(Section.getExternalName(), Section.getOrdinal(), Section.getSDAttributes()); writeSymbol(SD); } if (Section.isED()) { - GOFFSymbol ED(Section.getName(), Section.getOrdinal(), + GOFFSymbol ED(Section.getExternalName(), Section.getOrdinal(), Section.getParent()->getOrdinal(), Section.getEDAttributes()); ED.SectionLength = Asm.getSectionAddressSize(Section); writeSymbol(ED); @@ -329,8 +329,9 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) { if (Section.isPR()) { MCSectionGOFF *Parent = Section.getParent(); - GOFFSymbol PR(Section.getName(), Section.getOrdinal(), Parent->getOrdinal(), - Parent->getEDAttributes(), Section.getPRAttributes()); + GOFFSymbol PR(Section.getExternalName(), Section.getOrdinal(), + Parent->getOrdinal(), Parent->getEDAttributes(), + Section.getPRAttributes()); PR.SectionLength = Asm.getSectionAddressSize(Section); if (Section.requiresNonZeroLength()) { // We cannot have a zero-length section for data. If we do, @@ -347,8 +348,8 @@ void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) { void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) { MCSectionGOFF &Section = static_cast(Symbol.getSection()); - GOFFSymbol LD(Symbol.getName(), Symbol.getIndex(), Section.getOrdinal(), - Section.getEDAttributes().NameSpace, + GOFFSymbol LD(Symbol.getExternalName(), Symbol.getIndex(), + Section.getOrdinal(), Section.getEDAttributes().NameSpace, GOFF::LDAttr{false, Symbol.getCodeData(), Symbol.getBindingStrength(), Symbol.getLinkage(), GOFF::ESD_AMODE_64, Symbol.getBindingScope()}); @@ -359,7 +360,8 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) { } void GOFFWriter::defineExtern(const MCSymbolGOFF &Symbol) { - GOFFSymbol ER(Symbol.getName(), Symbol.getIndex(), RootSD->getOrdinal(), + GOFFSymbol ER(Symbol.getExternalName(), Symbol.getIndex(), + RootSD->getOrdinal(), GOFF::ERAttr{Symbol.isIndirect(), Symbol.getCodeData(), Symbol.getBindingStrength(), Symbol.getLinkage(), GOFF::ESD_AMODE_64, Symbol.getBindingScope()}); @@ -695,25 +697,26 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F, Asm->reportError( Fixup.getLoc(), Twine("symbol ") - .concat(A.getName()) + .concat(A.getExternalName()) .concat(" must be defined for a relative immediate relocation")); return; } if (&A.getSection() != PSection) { + MCSectionGOFF &GOFFSection = static_cast(A.getSection()); Asm->reportError(Fixup.getLoc(), Twine("relative immediate relocation section mismatch: ") - .concat(A.getSection().getName()) + .concat(GOFFSection.getExternalName()) .concat(" of symbol ") - .concat(A.getName()) + .concat(A.getExternalName()) .concat(" <-> ") - .concat(PSection->getName())); + .concat(PSection->getExternalName())); return; } if (B) { Asm->reportError( Fixup.getLoc(), Twine("subtractive symbol ") - .concat(B->getName()) + .concat(B->getExternalName()) .concat(" not supported for a relative immediate relocation")); return; } @@ -767,9 +770,11 @@ void GOFFObjectWriter::recordRelocation(const MCFragment &F, default: Con = "(unknown)"; } - dbgs() << "Reloc " << N << ": " << Con << " Rptr: " << Sym->getName() - << " Pptr: " << PSection->getName() << " Offset: " << FixupOffset - << " Fixed Imm: " << FixedValue << "\n"; + dbgs() << "Reloc " << N << ": " << Con + << " Rptr: " << Sym->getExternalName() + << " Pptr: " << PSection->getExternalName() + << " Offset: " << FixupOffset << " Fixed Imm: " << FixedValue + << "\n"; }; (void)DumpReloc; diff --git a/llvm/lib/MC/MCAsmInfoGOFF.cpp b/llvm/lib/MC/MCAsmInfoGOFF.cpp index 4dc33943609db..325854a0e740f 100644 --- a/llvm/lib/MC/MCAsmInfoGOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoGOFF.cpp @@ -120,10 +120,15 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section, raw_ostream &OS) const { auto &Sec = const_cast(static_cast(Section)); + auto EmitExternalName = [&Sec, &OS]() { + if (Sec.hasExternalName()) + OS << Sec.getName() << " ALIAS C'" << Sec.getExternalName() << "'\n"; + }; switch (Sec.SymbolType) { case GOFF::ESD_ST_SectionDefinition: { OS << Sec.getName() << " CSECT\n"; Sec.Emitted = true; + EmitExternalName(); break; } case GOFF::ESD_ST_ElementDefinition: { @@ -134,6 +139,7 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section, GOFF::ESD_EXE_Unspecified, Sec.EDAttributes.IsReadOnly, 0, Sec.EDAttributes.FillByteValue, StringRef()); Sec.Emitted = true; + EmitExternalName(); } else OS << Sec.getName() << " CATTR\n"; break; @@ -151,6 +157,7 @@ void MCAsmInfoGOFF::printSwitchToSection(const MCSection &Section, Sec.PRAttributes.Executable, Sec.PRAttributes.BindingScope); ED->Emitted = true; Sec.Emitted = true; + EmitExternalName(); } else OS << ED->getName() << " CATTR PART(" << Sec.getName() << ")\n"; break; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp index d425b6520a200..d1c3253330f46 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp @@ -258,6 +258,8 @@ void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { emitXATTR(OS, Sym->getName(), Sym->isIndirect(), Sym->getLinkage(), Sym->getCodeData(), Sym->getBindingScope()); EmitEOL(); + if (Sym->hasExternalName()) + OS << Sym->getName() << " ALIAS C'" << Sym->getExternalName() << "'\n"; } if (EmitLabelAndEntry) { @@ -368,6 +370,8 @@ void SystemZHLASMAsmStreamer::finishImpl() { emitXATTR(OS, Sym.getName(), Sym.isIndirect(), Sym.getLinkage(), Sym.getCodeData(), Sym.getBindingScope()); EmitEOL(); + if (Sym.hasExternalName()) + OS << Sym.getName() << " ALIAS C'" << Sym.getExternalName() << "'\n"; } // Finish the assembly output. diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h index 4f9a4a0a97ed8..878600a67edbc 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h @@ -13,8 +13,10 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionGOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolGOFF.h" #include "llvm/Support/FormattedStream.h" #include #include @@ -58,6 +60,9 @@ class SystemZTargetStreamer : public MCTargetStreamer { virtual void emitMachine(StringRef CPUOrCommand) {}; + virtual void emitExternalName(MCSymbol *Sym, StringRef Name) {} + virtual void emitExternalName(MCSection *Sec, StringRef Name) {} + virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) { return nullptr; @@ -69,6 +74,12 @@ class SystemZTargetGOFFStreamer : public SystemZTargetStreamer { SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {} const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) override; + virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override { + static_cast(Sym)->setExternalName(Name); + } + virtual void emitExternalName(MCSection *Sec, StringRef Name) override { + static_cast(Sec)->setExternalName(Name); + } }; class SystemZTargetHLASMStreamer : public SystemZTargetStreamer { @@ -80,6 +91,12 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer { SystemZHLASMAsmStreamer &getHLASMStreamer(); const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi, const MCSymbol *Lo) override; + virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override { + static_cast(Sym)->setExternalName(Name); + } + virtual void emitExternalName(MCSection *Sec, StringRef Name) override { + static_cast(Sec)->setExternalName(Name); + } }; class SystemZTargetELFStreamer : public SystemZTargetStreamer { From 0d95dda1eeee690bb7c3ec425ebfed5a8a80517b Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Fri, 27 Feb 2026 10:19:03 -0800 Subject: [PATCH 20/58] [LoopInfo] Preserve profile information in makeLoopInvariant (#174171) When hoisting loop invariant instructions, we can preserve profile metadata because it depends solely on the condition (which is loop invariant) rather than where we are in the control flow graph. --- llvm/lib/Analysis/LoopInfo.cpp | 24 +++++++++++- .../invalidate-scev-after-hoisting.ll | 15 +++++-- .../Transforms/LoopSimplify/profile-info.ll | 39 +++++++++++++++++++ llvm/utils/profcheck-xfail.txt | 1 - 4 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Transforms/LoopSimplify/profile-info.ll diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index a364b21c64b01..7060a0bd9dcfa 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -34,6 +34,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/PrintPasses.h" +#include "llvm/IR/ProfDataUtils.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -54,6 +55,10 @@ static cl::opt VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo), cl::Hidden, cl::desc("Verify loop info (time consuming)")); +namespace llvm { +extern cl::opt ProfcheckDisableMetadataFixes; +} // end namespace llvm + //===----------------------------------------------------------------------===// // Loop implementation // @@ -79,6 +84,7 @@ bool Loop::makeLoopInvariant(Value *V, bool &Changed, Instruction *InsertPt, bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, Instruction *InsertPt, MemorySSAUpdater *MSSAU, ScalarEvolution *SE) const { + BasicBlock *OriginalParent = I->getParent(); // Test if the value is already loop-invariant. if (isLoopInvariant(I)) return true; @@ -109,11 +115,27 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, MSSAU->moveToPlace(MUD, InsertPt->getParent(), MemorySSA::BeforeTerminator); + // We want to preserve profile metadata if possible. However, we need to + // ensure that profile metadata would remain the same outside of the loop. + // Given at this point we know the conditional is loop-invariant, we just + // need to worry about other control flow in the loop conditioned on values + // that are potentially not independent of the condition of the instruction + // we are interested in hoisting. Given this is not knowable in the general + // case, we only hoist from a loop header (which covers a reasonable number + // of cases) where we are guaranteed to not run into problems. + SmallVector ProfileMetadataToPreserve; + if (!ProfcheckDisableMetadataFixes) + if (OriginalParent == getHeader()) + ProfileMetadataToPreserve.push_back(LLVMContext::MD_prof); + // There is possibility of hoisting this instruction above some arbitrary // condition. Any metadata defined on it can be control dependent on this // condition. Conservatively strip it here so that we don't give any wrong // information to the optimizer. - I->dropUnknownNonDebugMetadata(); + I->dropUnknownNonDebugMetadata(ProfileMetadataToPreserve); + + if (ProfileMetadataToPreserve.empty() && isa(I)) + setExplicitlyUnknownBranchWeightsIfProfiled(*I, "LoopInfo"); if (SE) SE->forgetBlockAndLoopDispositions(I); diff --git a/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll b/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll index bdd51c2b6bc53..79c3773ebb686 100644 --- a/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll +++ b/llvm/test/Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals ; RUN: opt -passes='loop(indvars,loop-deletion),verify,print' -S %s 2>&1| FileCheck %s ; Make sure the SCEV for %invar is invalidated properly when the instruction is @@ -123,13 +123,13 @@ outer.latch: br label %outer.header } -define void @test_pr58314() { +define void @test_pr58314() !prof !0 { ; CHECK-LABEL: @test_pr58314( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer.header: ; CHECK-NEXT: [[C:%.*]] = icmp ne i16 0, 0 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i1 false, i1 true +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i1 false, i1 true, !prof [[PROF1:![0-9]+]] ; CHECK-NEXT: br label [[INNER:%.*]] ; CHECK: inner: ; CHECK-NEXT: br i1 true, label [[INNER]], label [[OUTER_LATCH:%.*]] @@ -147,7 +147,7 @@ outer.header: inner: %c = icmp ne i16 0, 0 - %sel = select i1 %c, i1 false, i1 true + %sel = select i1 %c, i1 false, i1 true, !prof !1 br i1 true, label %inner, label %outer.latch outer.latch: @@ -156,3 +156,10 @@ outer.latch: exit: ret void } + +!0 = !{!"function_entry_count", i64 1000} +!1 = !{!"branch_weights", i32 4, i32 1} +;. +; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000} +; CHECK: [[PROF1]] = !{!"branch_weights", i32 4, i32 1} +;. diff --git a/llvm/test/Transforms/LoopSimplify/profile-info.ll b/llvm/test/Transforms/LoopSimplify/profile-info.ll new file mode 100644 index 0000000000000..409556646e64d --- /dev/null +++ b/llvm/test/Transforms/LoopSimplify/profile-info.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -passes="loop-simplify" -S %s | FileCheck %s + +define void @test_drop(i8 %a) !prof !0 { +; CHECK-LABEL: define void @test_drop( +; CHECK-SAME: i8 [[A:%.*]]) !prof [[PROF0:![0-9]+]] { +; CHECK-NEXT: [[HEADER_BACKEDGE2:.*:]] +; CHECK-NEXT: [[S:%.*]] = select i1 true, i1 true, i1 false, !prof [[PROF1:![0-9]+]] +; CHECK-NEXT: br label %[[HEADER:.*]] +; CHECK: [[HEADER]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0 +; CHECK-NEXT: [[OR_COND:%.*]] = select i1 true, i1 [[CMP]], i1 false +; CHECK-NEXT: br i1 [[OR_COND]], label %[[EXIT:.*]], label %[[HEADER_BACKEDGE:.*]] +; CHECK: [[HEADER_BACKEDGE]]: +; CHECK-NEXT: br label %[[HEADER]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +entry: + br label %header + +header: + br i1 false, label %header, label %body + +body: + %s = select i1 true, i1 true, i1 false, !prof !1 + %cmp = icmp eq i8 %a, 0 + br i1 %cmp, label %exit, label %header + +exit: + ret void +} + +!0 = !{!"function_entry_count", i64 1000} +!1 = !{!"branch_weights", i32 4, i32 1} +;. +; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000} +; CHECK: [[PROF1]] = !{!"unknown", !"LoopInfo"} +;. diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt index e78307ff6988d..c31a804b19997 100644 --- a/llvm/utils/profcheck-xfail.txt +++ b/llvm/utils/profcheck-xfail.txt @@ -137,7 +137,6 @@ Transforms/InstCombine/wcslen-1.ll Transforms/InstCombine/wcslen-3.ll Transforms/InstCombine/xor-and-or.ll Transforms/InstCombine/zext-bool-add-sub.ll -Transforms/LoopDeletion/invalidate-scev-after-hoisting.ll Transforms/LoopIdiom/AArch64/byte-compare-index.ll Transforms/LoopIdiom/AArch64/find-first-byte.ll Transforms/LowerAtomic/atomic-load.ll From 67a51ea34d25b4be246791af5df858167dce901c Mon Sep 17 00:00:00 2001 From: zhijian lin Date: Fri, 27 Feb 2026 13:24:34 -0500 Subject: [PATCH 21/58] [NFC][POWER] add Pre-Commit test case for Inefficient std::bit_floor(x) (#183363) add a pre-commit test case for Inefficient asm of std::bit_floor(x) for powerpc. --- llvm/test/CodeGen/PowerPC/bit_floor.ll | 91 ++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 llvm/test/CodeGen/PowerPC/bit_floor.ll diff --git a/llvm/test/CodeGen/PowerPC/bit_floor.ll b/llvm/test/CodeGen/PowerPC/bit_floor.ll new file mode 100644 index 0000000000000..916ef0a9451c4 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/bit_floor.ll @@ -0,0 +1,91 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -ppc-asm-full-reg-names < %s | FileCheck --check-prefix=AIX32 %s +; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff -ppc-asm-full-reg-names < %s | FileCheck --check-prefixes=AIX64 %s +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -ppc-asm-full-reg-names < %s | FileCheck --check-prefixes=LNX64 %s + +define noundef range(i32 0, -2147483647) i32 @_Z10bitfloor32j(i32 noundef %x) local_unnamed_addr { +; AIX32-LABEL: _Z10bitfloor32j: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: cntlzw r4, r3 +; AIX32-NEXT: lis r5, -32768 +; AIX32-NEXT: cmplwi r3, 0 +; AIX32-NEXT: srw r4, r5, r4 +; AIX32-NEXT: iseleq r3, 0, r4 +; AIX32-NEXT: blr +; +; AIX64-LABEL: _Z10bitfloor32j: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: cntlzw r4, r3 +; AIX64-NEXT: lis r5, -32768 +; AIX64-NEXT: cmplwi r3, 0 +; AIX64-NEXT: srw r4, r5, r4 +; AIX64-NEXT: iseleq r3, 0, r4 +; AIX64-NEXT: blr +; +; LNX64-LABEL: _Z10bitfloor32j: +; LNX64: # %bb.0: # %entry +; LNX64-NEXT: cntlzw r4, r3 +; LNX64-NEXT: cmplwi r3, 0 +; LNX64-NEXT: lis r5, -32768 +; LNX64-NEXT: srw r4, r5, r4 +; LNX64-NEXT: iseleq r3, 0, r4 +; LNX64-NEXT: blr +entry: + %cmp.i = icmp eq i32 %x, 0 + %0 = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %x, i1 true) + %shl.i = lshr exact i32 -2147483648, %0 + %cond.i = select i1 %cmp.i, i32 0, i32 %shl.i + ret i32 %cond.i +} + +declare i32 @llvm.ctlz.i32(i32, i1 immarg) + +define noundef range(i64 0, -9223372036854775807) i64 @_Z10bitfloor64y(i64 noundef %x) local_unnamed_addr { +; AIX32-LABEL: _Z10bitfloor64y: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: cntlzw r6, r4 +; AIX32-NEXT: cntlzw r5, r3 +; AIX32-NEXT: lis r7, -32768 +; AIX32-NEXT: cmplwi r3, 0 +; AIX32-NEXT: addi r6, r6, 32 +; AIX32-NEXT: iseleq r5, r6, r5 +; AIX32-NEXT: or. r3, r4, r3 +; AIX32-NEXT: addi r6, r5, -32 +; AIX32-NEXT: subfic r8, r5, 32 +; AIX32-NEXT: srw r5, r7, r5 +; AIX32-NEXT: srw r6, r7, r6 +; AIX32-NEXT: slw r8, r7, r8 +; AIX32-NEXT: or r3, r8, r6 +; AIX32-NEXT: iseleq r4, 0, r3 +; AIX32-NEXT: iseleq r3, 0, r5 +; AIX32-NEXT: blr +; +; AIX64-LABEL: _Z10bitfloor64y: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: li r5, 1 +; AIX64-NEXT: cntlzd r4, r3 +; AIX64-NEXT: cmpldi r3, 0 +; AIX64-NEXT: rldic r5, r5, 63, 0 +; AIX64-NEXT: srd r4, r5, r4 +; AIX64-NEXT: iseleq r3, 0, r4 +; AIX64-NEXT: blr +; +; LNX64-LABEL: _Z10bitfloor64y: +; LNX64: # %bb.0: # %entry +; LNX64-NEXT: li r5, 1 +; LNX64-NEXT: cntlzd r4, r3 +; LNX64-NEXT: cmpldi r3, 0 +; LNX64-NEXT: rldic r5, r5, 63, 0 +; LNX64-NEXT: srd r4, r5, r4 +; LNX64-NEXT: iseleq r3, 0, r4 +; LNX64-NEXT: blr +entry: + %cmp.i = icmp eq i64 %x, 0 + %0 = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %x, i1 true) + %shl.i = lshr exact i64 -9223372036854775808, %0 + %cond.i = select i1 %cmp.i, i64 0, i64 %shl.i + ret i64 %cond.i +} + +declare i64 @llvm.ctlz.i64(i64, i1 immarg) + From c49460bae76c873725ae77d5f9b4d6239b7c40a7 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Fri, 27 Feb 2026 12:27:39 -0600 Subject: [PATCH 22/58] [flang-rt] Enable more runtime functions for the GPU target (#183649) Summary: This enables primarily `stop.cpp` and `descriptor.cpp`. Requires a little bit of wrangling to get it to compile. Unlike the CUDA build, this build uses an in-tree libc++ configured for the GPU. This is configured without thread support, environment, or filesystem, and it is not POSIX at all. So, no mutexes, pthreads, or get/setenv. I tested stop, but i don't know if it's actually legal to exit from OpenMP offloading. --- flang-rt/include/flang-rt/runtime/lock.h | 2 +- flang-rt/include/flang-rt/runtime/tools.h | 2 +- flang-rt/lib/runtime/CMakeLists.txt | 3 ++ flang-rt/lib/runtime/descriptor.cpp | 2 +- flang-rt/lib/runtime/environment.cpp | 8 ++- flang-rt/lib/runtime/stop.cpp | 8 +++ flang-rt/lib/runtime/terminator.cpp | 3 ++ flang/include/flang/Common/api-attrs.h | 12 +++++ .../fortran/target-descriptor-ops.f90 | 50 +++++++++++++++++++ 9 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 offload/test/offloading/fortran/target-descriptor-ops.f90 diff --git a/flang-rt/include/flang-rt/runtime/lock.h b/flang-rt/include/flang-rt/runtime/lock.h index 7c88534245733..7147c3a6b940b 100644 --- a/flang-rt/include/flang-rt/runtime/lock.h +++ b/flang-rt/include/flang-rt/runtime/lock.h @@ -16,7 +16,7 @@ // Avoid if possible to avoid introduction of C++ runtime // library dependence. -#ifndef _WIN32 +#if !defined(_WIN32) && !RT_GPU_TARGET #define USE_PTHREADS 1 #else #undef USE_PTHREADS diff --git a/flang-rt/include/flang-rt/runtime/tools.h b/flang-rt/include/flang-rt/runtime/tools.h index 1939c4d907be4..a45c2ac98f2fa 100644 --- a/flang-rt/include/flang-rt/runtime/tools.h +++ b/flang-rt/include/flang-rt/runtime/tools.h @@ -35,7 +35,7 @@ #define RT_PRETTY_FUNCTION __func__ #endif -#if defined(RT_DEVICE_COMPILATION) +#if defined(RT_DEVICE_COMPILATION) || RT_GPU_TARGET // Use the pseudo lock and pseudo file unit implementations // for the device. #define RT_USE_PSEUDO_LOCK 1 diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt index 9fa8376e9b99c..d18ce6caccaa3 100644 --- a/flang-rt/lib/runtime/CMakeLists.txt +++ b/flang-rt/lib/runtime/CMakeLists.txt @@ -109,9 +109,11 @@ set(gpu_sources copy.cpp derived-api.cpp derived.cpp + descriptor.cpp dot-product.cpp edit-output.cpp extrema.cpp + environment.cpp findloc.cpp format.cpp inquiry.cpp @@ -127,6 +129,7 @@ set(gpu_sources product.cpp ragged.cpp stat.cpp + stop.cpp sum.cpp support.cpp terminator.cpp diff --git a/flang-rt/lib/runtime/descriptor.cpp b/flang-rt/lib/runtime/descriptor.cpp index 04bbb3877a0d0..6c9e76afb117e 100644 --- a/flang-rt/lib/runtime/descriptor.cpp +++ b/flang-rt/lib/runtime/descriptor.cpp @@ -8,10 +8,10 @@ #include "flang-rt/runtime/descriptor.h" #include "ISO_Fortran_util.h" -#include "memory.h" #include "flang-rt/runtime/allocator-registry.h" #include "flang-rt/runtime/derived.h" #include "flang-rt/runtime/environment.h" +#include "flang-rt/runtime/memory.h" #include "flang-rt/runtime/stat.h" #include "flang-rt/runtime/terminator.h" #include "flang-rt/runtime/type-info.h" diff --git a/flang-rt/lib/runtime/environment.cpp b/flang-rt/lib/runtime/environment.cpp index ae4d6d305f409..53e13cd929bf8 100644 --- a/flang-rt/lib/runtime/environment.cpp +++ b/flang-rt/lib/runtime/environment.cpp @@ -8,7 +8,7 @@ #include "flang-rt/runtime/environment.h" #include "environment-default-list.h" -#include "memory.h" +#include "flang-rt/runtime/memory.h" #include "flang-rt/runtime/tools.h" #include #include @@ -19,10 +19,11 @@ #ifdef _MSC_VER extern char **_environ; #endif -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || RT_GPU_TARGET // FreeBSD has environ in crt rather than libc. Using "extern char** environ" // in the code of a shared library makes it fail to link with -Wl,--no-undefined // See https://reviews.freebsd.org/D30842#840642 +// GPU targets do not provide environ. #else extern char **environ; #endif @@ -51,6 +52,8 @@ static void (*PostConfigEnvCallback[ExecutionEnvironment::nConfigEnvCallback])( int, const char *[], const char *[], const EnvironmentDefaultList *){ nullptr}; +// No environment support on the GPU. +#if !RT_GPU_TARGET static void SetEnvironmentDefaults(const EnvironmentDefaultList *envDefaults) { if (!envDefaults) { return; @@ -314,6 +317,7 @@ std::int32_t ExecutionEnvironment::UnsetEnv( return status; } +#endif extern "C" { diff --git a/flang-rt/lib/runtime/stop.cpp b/flang-rt/lib/runtime/stop.cpp index 75fa64c4c0039..5abb80af7e66d 100644 --- a/flang-rt/lib/runtime/stop.cpp +++ b/flang-rt/lib/runtime/stop.cpp @@ -24,10 +24,14 @@ extern "C" { [[maybe_unused]] static void DescribeIEEESignaledExceptions() { +#if defined(RT_DEVICE_COMPILATION) || RT_GPU_TARGET + unsigned excepts{}; // No fenv support on the device. +#else #ifdef fetestexcept // a macro in some environments; omit std:: auto excepts{fetestexcept(FE_ALL_EXCEPT)}; #else auto excepts{std::fetestexcept(FE_ALL_EXCEPT)}; +#endif #endif if (excepts) { std::fputs("IEEE arithmetic exceptions signaled:", stderr); @@ -61,8 +65,10 @@ extern "C" { } static void CloseAllExternalUnits(const char *why) { +#if !RT_GPU_TARGET Fortran::runtime::io::IoErrorHandler handler{why}; Fortran::runtime::io::ExternalFileUnit::CloseAll(handler); +#endif } [[noreturn]] RT_API_ATTRS void RTNAME(StopStatement)( @@ -134,6 +140,7 @@ static void CloseAllExternalUnits(const char *why) { #endif } +#if !RT_GPU_TARGET static bool StartPause() { if (Fortran::runtime::io::IsATerminal(0)) { Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"}; @@ -173,6 +180,7 @@ void RTNAME(PauseStatementText)(const char *code, std::size_t length) { EndPause(); } } +#endif [[noreturn]] void RTNAME(FailImageStatement)() { CloseAllExternalUnits("FAIL IMAGE statement"); diff --git a/flang-rt/lib/runtime/terminator.cpp b/flang-rt/lib/runtime/terminator.cpp index e8d64223919e4..2c06c8de74d0f 100644 --- a/flang-rt/lib/runtime/terminator.cpp +++ b/flang-rt/lib/runtime/terminator.cpp @@ -70,8 +70,11 @@ RT_API_ATTRS void Terminator::CrashHeader() const { std::printf("\n"); #else fputc('\n', stderr); + // TODO: This should flush the buffers through the RPC interface. +#if !RT_GPU_TARGET // FIXME: re-enable the flush along with the IO enabling. io::FlushOutputOnCrash(*this); +#endif #endif NotifyOtherImagesOfErrorTermination(EXIT_FAILURE); #if defined(RT_DEVICE_COMPILATION) diff --git a/flang/include/flang/Common/api-attrs.h b/flang/include/flang/Common/api-attrs.h index fd524ee34ccff..efb495e7f132e 100644 --- a/flang/include/flang/Common/api-attrs.h +++ b/flang/include/flang/Common/api-attrs.h @@ -133,6 +133,18 @@ #undef RT_DEVICE_COMPILATION #endif +/* + * RT_GPU_TARGET is defined when compiling natively for a GPU + * target (AMDGPU or NVPTX) using a GPU-hosted libc/libc++. This is + * distinct from RT_DEVICE_COMPILATION which covers CUDA and OpenMP + * offload paths that use separate host/device compilation. + */ +#if defined(__AMDGPU__) || defined(__NVPTX__) +#define RT_GPU_TARGET 1 +#else +#undef RT_GPU_TARGET +#endif + /* * Recurrence in the call graph prevents computing minimal stack size * required for a kernel execution. This macro can be used to disable diff --git a/offload/test/offloading/fortran/target-descriptor-ops.f90 b/offload/test/offloading/fortran/target-descriptor-ops.f90 new file mode 100644 index 0000000000000..43dae03b33995 --- /dev/null +++ b/offload/test/offloading/fortran/target-descriptor-ops.f90 @@ -0,0 +1,50 @@ +! REQUIRES: flang, amdgpu + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +program main + implicit none + integer :: result + + ! CHECK: 100 + result = 0 + !$omp target map(from: result) + block + integer, allocatable :: arr(:) + integer :: i + allocate(arr(4)) + do i = 1, 4 + arr(i) = i * 10 + end do + result = arr(1) + arr(2) + arr(3) + arr(4) + deallocate(arr) + end block + !$omp end target + print *, result + + ! CHECK: 21 + result = 0 + !$omp target map(from: result) + block + integer, allocatable :: mat(:,:) + allocate(mat(2, 3)) + mat(1,1) = 1; mat(2,1) = 2 + mat(1,2) = 3; mat(2,2) = 4 + mat(1,3) = 5; mat(2,3) = 6 + result = mat(1,1) + mat(2,1) + mat(1,2) + mat(2,2) + mat(1,3) + mat(2,3) + deallocate(mat) + end block + !$omp end target + print *, result + + ! CHECK: 17 + result = 0 + !$omp target map(from: result) + block + integer, allocatable :: arr(:) + allocate(arr(8)) + result = size(arr) + lbound(arr, 1) + ubound(arr, 1) + deallocate(arr) + end block + !$omp end target + print *, result +end program main From 6301243a5d69146b4b76ac4233b0b2f6a3c31616 Mon Sep 17 00:00:00 2001 From: Kshitij Paranjape Date: Sat, 28 Feb 2026 00:03:59 +0530 Subject: [PATCH 23/58] Reapply "[ValueTracking] Propagate sign information out of loop" (#182512) LLVM converts sqrt libcall to intrinsic call if the argument is within the range(greater than or equal to 0.0). In this case the compiler is not able to deduce the non-negativity on its own. Extended ValueTracking to understand such loops. Have created new ABI's for matching Intrinsics with three operands (those existed only for 2 operands) `matchSimpleTernaryIntrinsicRecurrence` and `matchThreeInputRecurrence`. Fixes https://github.com/llvm/llvm-project/issues/174813 --- llvm/include/llvm/Analysis/ValueTracking.h | 18 ++ llvm/lib/Analysis/ValueTracking.cpp | 81 +++++ .../AggressiveInstCombine/X86/pr175590.ll | 302 ++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 1cd88fd89aea2..5f1e7773be8d3 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -1001,6 +1001,24 @@ LLVM_ABI bool matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I, PHINode *&P, Value *&Init, Value *&OtherOp); +/// Attempt to match a simple value-accumulating recurrence of the form: +/// %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge] +/// %llvm.intrinsic = call Ty @llvm.intrinsic(%OtherOp0, %OtherOp1, +/// %llvm.intrinsic.acc) +/// OR +/// %llvm.intrinsic.acc = phi Ty [%Init, %Entry], [%llvm.intrinsic, %backedge] +/// %llvm.intrinsic = call Ty @llvm.intrinsic(%llvm.intrinsic.acc, %OtherOp0, +/// %OtherOp1) +/// +/// The recurrence relation is of kind: +/// X_0 = %a (initial value), +/// X_i = call @llvm.ternary.intrinsic(X_i-1, %b, %c) +/// Where %b, %c are not required to be loop-invariant. +LLVM_ABI bool matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I, + PHINode *&P, Value *&Init, + Value *&OtherOp0, + Value *&OtherOp1); + /// Return true if RHS is known to be implied true by LHS. Return false if /// RHS is known to be implied false by LHS. Otherwise, return std::nullopt if /// no implication can be made. A & B must be i1 (boolean) values or a vector of diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index ce8e27fef5e8a..2364fdddef31d 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5925,6 +5925,34 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, } } + // Look for the case of a for loop which has a positive + // initial value and is incremented by a squared value. + // This will propagate sign information out of such loops. + if (P->getNumIncomingValues() != 2 || Known.cannotBeOrderedLessThanZero()) + break; + for (unsigned I = 0; I < 2; I++) { + Value *RecurValue = P->getIncomingValue(1 - I); + IntrinsicInst *II = dyn_cast(RecurValue); + if (!II) + continue; + Value *R, *L, *Init; + PHINode *PN; + if (matchSimpleTernaryIntrinsicRecurrence(II, PN, Init, L, R) && + PN == P) { + switch (II->getIntrinsicID()) { + case Intrinsic::fma: + case Intrinsic::fmuladd: { + KnownFPClass KnownStart; + computeKnownFPClass(Init, DemandedElts, InterestedClasses, KnownStart, + Q, Depth + 1); + if (KnownStart.cannotBeOrderedLessThanZero() && L == R && + isGuaranteedNotToBeUndef(L, Q.AC, Q.CxtI, Q.DT, Depth + 1)) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + break; + } + } + } + } break; } case Instruction::BitCast: { @@ -9245,6 +9273,40 @@ static bool matchTwoInputRecurrence(const PHINode *PN, InstTy *&Inst, return false; } +template +static bool matchThreeInputRecurrence(const PHINode *PN, InstTy *&Inst, + Value *&Init, Value *&OtherOp0, + Value *&OtherOp1) { + if (PN->getNumIncomingValues() != 2) + return false; + + for (unsigned I = 0; I != 2; ++I) { + if (auto *Operation = dyn_cast(PN->getIncomingValue(I)); + Operation && Operation->getNumOperands() >= 3) { + Value *Op0 = Operation->getOperand(0); + Value *Op1 = Operation->getOperand(1); + Value *Op2 = Operation->getOperand(2); + + if (Op0 != PN && Op1 != PN && Op2 != PN) + continue; + + Inst = Operation; + Init = PN->getIncomingValue(!I); + if (Op0 == PN) { + OtherOp0 = Op1; + OtherOp1 = Op2; + } else if (Op1 == PN) { + OtherOp0 = Op0; + OtherOp1 = Op2; + } else { + OtherOp0 = Op0; + OtherOp1 = Op1; + } + return true; + } + } + return false; +} bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start, Value *&Step) { // We try to match a recurrence of the form: @@ -9281,6 +9343,25 @@ bool llvm::matchSimpleBinaryIntrinsicRecurrence(const IntrinsicInst *I, return P && matchTwoInputRecurrence(P, II, Init, OtherOp) && II == I; } +bool llvm::matchSimpleTernaryIntrinsicRecurrence(const IntrinsicInst *I, + PHINode *&P, Value *&Init, + Value *&OtherOp0, + Value *&OtherOp1) { + if (I->arg_size() != 3 || I->getType() != I->getArgOperand(0)->getType() || + I->getType() != I->getArgOperand(1)->getType() || + I->getType() != I->getArgOperand(2)->getType()) + return false; + IntrinsicInst *II = nullptr; + P = dyn_cast(I->getArgOperand(0)); + if (!P) { + P = dyn_cast(I->getArgOperand(1)); + if (!P) + P = dyn_cast(I->getArgOperand(2)); + } + return P && matchThreeInputRecurrence(P, II, Init, OtherOp0, OtherOp1) && + II == I; +} + /// Return true if "icmp Pred LHS RHS" is always true. static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS, const Value *RHS) { diff --git a/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll new file mode 100644 index 0000000000000..9f54c9a3e9a6f --- /dev/null +++ b/llvm/test/Transforms/AggressiveInstCombine/X86/pr175590.ll @@ -0,0 +1,302 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s +target triple = "x86_64-unknown-linux-gnu" +define double @CompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @CompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]]) +; CHECK-NEXT: ret double [[SQRT]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double noundef [[SUB]], double noundef [[SUB]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double noundef %sub, double noundef %sub, double %RMSD.0) + br label %for.cond +} + +define double @shuffledCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @shuffledCompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ], [ 0.000000e+00, %[[ENTRY]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]]) +; CHECK-NEXT: ret double [[CALL]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double noundef [[SUB]], double noundef [[SUB]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ %fmacall, %for.body ], [ 0.000000e+00, %entry ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double noundef %sub, double noundef %sub, double %RMSD.0) + br label %for.cond +} + +define double @fmaCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @fmaCompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[RMSD_0]]) +; CHECK-NEXT: ret double [[SQRT]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fma.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fma.f64(double %sub, double %sub, double %RMSD.0) + br label %for.cond +} + +define double @nonSquareCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @nonSquareCompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]]) +; CHECK-NEXT: ret double [[CALL]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[ADD:%.*]] = fadd double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[ADD]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ 0.000000e+00, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %add = fadd double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double %sub, double %add, double %RMSD.0) + br label %for.cond +} + +define double @negInitialCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @negInitialCompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ -1.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]]) +; CHECK-NEXT: ret double [[CALL]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ -1.000000e+00, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %RMSD.0) + br label %for.cond +} + +define double @notMatchingRecurrenceCompareDistmats(double noundef %distmat1_, double noundef %distmat2_) { +; CHECK-LABEL: define double @notMatchingRecurrenceCompareDistmats( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ -1.000000e+00, %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[CALL:%.*]] = call double @sqrt(double noundef [[RMSD_0]]) +; CHECK-NEXT: ret double [[CALL]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double [[SUB]], double [[SUB]], double [[SUB]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ -1.000000e+00, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %call = call double @sqrt(double noundef %RMSD.0) + ret double %call + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double %sub, double %sub, double %sub) + br label %for.cond +} + +define i1 @test_phi_operand_crash(ptr %arena, i1 %exitcond) { +; CHECK-LABEL: define i1 @test_phi_operand_crash( +; CHECK-SAME: ptr [[ARENA:%.*]], i1 [[EXITCOND:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[DOT026:%.*]] = phi double [ 0.000000e+00, %[[ENTRY]] ], [ 1.000000e+00, %[[LOOP_BACKEDGE:.*]] ] +; CHECK-NEXT: br i1 true, label %[[LOAD_BLOCK:.*]], label %[[ZERO_BLOCK:.*]] +; CHECK: [[ZERO_BLOCK]]: +; CHECK-NEXT: br label %[[LOOP_BACKEDGE]] +; CHECK: [[LOAD_BLOCK]]: +; CHECK-NEXT: [[LOADED_VAL:%.*]] = load double, ptr [[ARENA]], align 8 +; CHECK-NEXT: br label %[[LOOP_BACKEDGE]] +; CHECK: [[LOOP_BACKEDGE]]: +; CHECK-NEXT: [[DOT0_I22:%.*]] = phi double [ [[LOADED_VAL]], %[[LOAD_BLOCK]] ], [ 0.000000e+00, %[[ZERO_BLOCK]] ] +; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[FMA_RESULT:%.*]] = tail call double @llvm.fmuladd.f64(double 0.000000e+00, double [[DOT0_I22]], double [[DOT026]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp oge double [[FMA_RESULT]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + br label %loop + +loop: + %.026 = phi double [ 0.000000e+00, %entry ], [ 1.000000e+00, %loop_backedge ] + br i1 true, label %load_block, label %zero_block + +zero_block: + br label %loop_backedge + +load_block: + %loaded_val = load double, ptr %arena, align 8 + br label %loop_backedge + +loop_backedge: + %.0.i22 = phi double [ %loaded_val, %load_block ], [ 0.000000e+00, %zero_block ] + br i1 %exitcond, label %loop, label %exit + +exit: + %fma_result = tail call double @llvm.fmuladd.f64(double 0.000000e+00, double %.0.i22, double %.026) + %cmp = fcmp oge double %fma_result, 0.000000e+00 + ret i1 %cmp +} + +define i1 @test_ternary_recurrence_crash(double noundef %distmat1_, double noundef %distmat2_, double %x) { +; CHECK-LABEL: define i1 @test_ternary_recurrence_crash( +; CHECK-SAME: double noundef [[DISTMAT1_:%.*]], double noundef [[DISTMAT2_:%.*]], double [[X:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[INIT_VAL:%.*]] = call double @llvm.sqrt.f64(double [[X]]) +; CHECK-NEXT: br label %[[FOR_COND:.*]] +; CHECK: [[FOR_COND]]: +; CHECK-NEXT: [[RMSD_0:%.*]] = phi double [ [[INIT_VAL]], %[[ENTRY]] ], [ [[FMACALL:%.*]], %[[FOR_BODY:.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ true, %[[ENTRY]] ], [ false, %[[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP:.*]] +; CHECK: [[FOR_COND_CLEANUP]]: +; CHECK-NEXT: [[RES:%.*]] = fcmp oge double [[RMSD_0]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[RES]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[SUB:%.*]] = fsub double [[DISTMAT1_]], [[DISTMAT2_]] +; CHECK-NEXT: [[FMACALL]] = call double @llvm.fmuladd.f64(double noundef [[SUB]], double noundef [[SUB]], double [[RMSD_0]]) +; CHECK-NEXT: br label %[[FOR_COND]] +; +entry: + %init_val = call double @llvm.sqrt.f64(double %x) + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %RMSD.0 = phi double [ %init_val, %entry ], [ %fmacall, %for.body ] + %cmp = phi i1 [ true, %entry ], [ false, %for.body ] + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %res = fcmp oge double %RMSD.0, 0.000000e+00 + ret i1 %res + +for.body: ; preds = %for.cond + %sub = fsub double %distmat1_, %distmat2_ + %fmacall = call double @llvm.fmuladd.f64(double noundef %sub, double noundef %sub, double %RMSD.0) + br label %for.cond +} + +declare double @llvm.fmuladd.f64(double, double, double) + +declare double @llvm.fma.f64(double, double, double) + +declare double @sqrt(double noundef) From ca0e7d31d05bea7b6d29a420e9b1c756a1845e95 Mon Sep 17 00:00:00 2001 From: kwyatt-ext Date: Fri, 27 Feb 2026 12:43:18 -0600 Subject: [PATCH 24/58] [flang] [flang-rt] Addition of the Fortran 2023 TOKENIZE intrinsic. (#181030) This implements the TOKENIZE intrinsic per the Fortran 2023 Standard. TOKENIZE is a more complicated addition to the flang intrinsics, as it is the first subroutine that has multiple unique footprints. Intrinsic functions have already addressed this challenge, however subroutines and functions are processed slightly differently and the function code was not a good 1:1 solution for the subroutines. To solve this the function code was used as an example to create error buffering within the intrinsics Process and select the most appropriate error message for a given subroutine footprint. A simple FIR compile test was added to show the proper compilation of each case. A thorough negative path test has also been added, ensuring that all possible errors are reported as expected. Testing prior to commit: = check-flang ========================================== ``` Testing Time: 139.51s Total Discovered Tests: 4153 Unsupported : 77 (1.85%) Passed : 4065 (97.88%) Expectedly Failed: 11 (0.26%) FLANG Container Test completed 2 minutes (160 s). Total Time: 2 minutes (160 s) Completed : Wed Feb 11 04:05:50 PM CST 2026 ``` = check-flang-rt ========================================== ``` Testing Time: 1.55s Total Discovered Tests: 258 Passed: 258 (100.00%) FLANG Container Test completed 0 minutes (55 s). Total Time: 0 minutes (56 s) Completed : Wed Feb 11 04:08:32 PM CST 2026 ``` = llvm-test-suite ========================================== ``` Testing Time: 1886.64s Total Discovered Tests: 6926 Passed: 6926 (100.00%) CCE SLES Container debug compile completed 31 minutes (1895 s). CCE SLES Container debug install completed in 0 minutes (0 s). Total Time: 31 minutes (1895 s) Completed : Wed Feb 11 05:46:52 PM CST 2026 ``` Additionally, (FYI) an executable test has been written and will be added to the llvm-test-suite under a separate PR. --------- Co-authored-by: Kevin Wyatt --- flang-rt/lib/runtime/character.cpp | 437 ++++++++++++++++++ flang-rt/unittests/Runtime/CharacterTest.cpp | 208 +++++++++ .../flang/Optimizer/Builder/IntrinsicCall.h | 1 + .../Optimizer/Builder/Runtime/Character.h | 16 + flang/include/flang/Runtime/character.h | 7 + flang/lib/Evaluate/intrinsics.cpp | 107 ++++- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 102 ++++ .../Optimizer/Builder/Runtime/Character.cpp | 29 ++ flang/test/Lower/Intrinsics/tokenize.f90 | 27 ++ flang/test/Semantics/tokenize-errors.f90 | 267 +++++++++++ 10 files changed, 1200 insertions(+), 1 deletion(-) create mode 100644 flang/test/Lower/Intrinsics/tokenize.f90 create mode 100644 flang/test/Semantics/tokenize-errors.f90 diff --git a/flang-rt/lib/runtime/character.cpp b/flang-rt/lib/runtime/character.cpp index 04c9055f84498..a663643fa18cc 100644 --- a/flang-rt/lib/runtime/character.cpp +++ b/flang-rt/lib/runtime/character.cpp @@ -571,6 +571,427 @@ static RT_API_ATTRS void MaxMin(Descriptor &accumulator, const Descriptor &x, } } +template +static inline RT_API_ATTRS bool TokenizeIsInSet( + CHAR ch, const CHAR *set, std::size_t setChars) { + for (std::size_t j{0}; j < setChars; ++j) { + if (set[j] == ch) { + return true; + } + } + return false; +} + +// Pad the token with spaces. +template +static inline RT_API_ATTRS void TokenizeFillBlanks( + CHAR *to, std::size_t chars) { + if (chars == 0) { + return; + } + if constexpr (std::is_same_v) { + runtime::memset(to, ' ', chars); + } else { + for (std::size_t j{0}; j < chars; ++j) { + to[j] = static_cast(' '); + } + } +} + +struct TokenizeAnalysis { + std::size_t tokenCount{0}; + std::size_t maxTokenLen{0}; // in characters +}; + +template +static RT_API_ATTRS TokenizeAnalysis AnalyzeTokenize(const CHAR *str, + std::size_t strChars, const CHAR *set, std::size_t setChars) { + TokenizeAnalysis analysis; + + // Empty STRING should return one empty token, per Fortran standard. + if (strChars == 0) { + analysis.tokenCount = 1; + analysis.maxTokenLen = 0; + return analysis; + } + if (setChars == 0) { + analysis.tokenCount = 1; + analysis.maxTokenLen = strChars; + return analysis; + } + + // Split STRING at each delimiter character. This produces empty tokens + // when delimiters are consecutive or when STRING starts/ends with a + // delimiter. + std::size_t tokenStart{0}; + for (std::size_t pos{0}; pos < strChars; ++pos) { + if (TokenizeIsInSet(str[pos], set, setChars)) { + analysis.maxTokenLen = std::max(analysis.maxTokenLen, pos - tokenStart); + analysis.tokenCount++; + tokenStart = pos + 1; + } + } + analysis.maxTokenLen = std::max(analysis.maxTokenLen, strChars - tokenStart); + analysis.tokenCount++; + + return analysis; +} +// Allocates and populates the result arrays for TOKENIZE Form 1. +template +static RT_API_ATTRS void TokenizeFillForm1(Descriptor &tokens, + Descriptor *separator, const Descriptor &string, const CHAR *str, + std::size_t strChars, const CHAR *set, std::size_t setChars, + const TokenizeAnalysis &analysis, Terminator &terminator) { + + // (Re)allocate TOKENS. + if (tokens.IsAllocated()) { + tokens.Deallocate(); + } + SubscriptValue tokensExtent[1]{ + static_cast(analysis.tokenCount)}; + std::size_t tokenElemBytes{ + analysis.tokenCount == 0 ? 0 : analysis.maxTokenLen * sizeof(CHAR)}; + tokens.Establish(string.type(), tokenElemBytes, nullptr, 1, tokensExtent, + CFI_attribute_allocatable); + tokens.GetDimension(0).SetBounds(1, tokensExtent[0]); + if (tokens.Allocate(kNoAsyncObject) != CFI_SUCCESS) { + terminator.Crash("TOKENIZE: could not allocate TOKENS array"); + } + + // (Re)allocate SEPARATOR if present. + std::size_t sepCount{analysis.tokenCount > 0 ? analysis.tokenCount - 1 : 0}; + std::size_t sepElemBytes{sizeof(CHAR)}; + if (separator) { + if (separator->IsAllocated()) { + separator->Deallocate(); + } + SubscriptValue sepExtent[1]{static_cast(sepCount)}; + separator->Establish(string.type(), sepElemBytes, nullptr, 1, sepExtent, + CFI_attribute_allocatable); + separator->GetDimension(0).SetBounds(1, sepExtent[0]); + if (separator->Allocate(kNoAsyncObject) != CFI_SUCCESS) { + terminator.Crash("TOKENIZE: could not allocate SEPARATOR array"); + } + } + + if (analysis.tokenCount == 0) { + return; + } + + // Populate tokens and separators. + if (setChars == 0) { + // One token (possibly empty) equal to STRING. + if (tokenElemBytes > 0) { + CHAR *tokDest{tokens.OffsetElement(0)}; + if (strChars > 0) { + runtime::memcpy(tokDest, str, strChars * sizeof(CHAR)); + } + TokenizeFillBlanks(tokDest + strChars, analysis.maxTokenLen - strChars); + } + return; + } + + std::size_t tokenIndex{0}; + std::size_t sepIndex{0}; + + auto storeToken = [&](std::size_t tokenStart, std::size_t tokenEnd) { + std::size_t tokenLen{tokenEnd - tokenStart}; + if (tokenElemBytes > 0) { + // Each element is stored in a fixed-size slot of `tokenElemBytes`. + CHAR *tokDest{tokens.OffsetElement(tokenIndex * tokenElemBytes)}; + if (tokenLen > 0) { + runtime::memcpy(tokDest, str + tokenStart, tokenLen * sizeof(CHAR)); + } + TokenizeFillBlanks(tokDest + tokenLen, analysis.maxTokenLen - tokenLen); + } + ++tokenIndex; + }; + + // Split at each delimiter character, producing empty tokens at boundaries + // and between consecutive delimiters. + std::size_t tokenStart{0}; + for (std::size_t pos{0}; pos < strChars; ++pos) { + if (TokenizeIsInSet(str[pos], set, setChars)) { + storeToken(tokenStart, pos); + if (separator) { + CHAR *sepDest{separator->OffsetElement(sepIndex * sepElemBytes)}; + sepDest[0] = str[pos]; + ++sepIndex; + } + tokenStart = pos + 1; + } + } + storeToken(tokenStart, strChars); +} + +template +static RT_API_ATTRS void TokenizeStoreIntAt( + const Descriptor &result, std::size_t at, std::int64_t value) { + StoreIntegerAt{}(result, at, value); +} + +using TokenizeStoreIntFn = void (*)( + const Descriptor &, std::size_t, std::int64_t); + +static RT_API_ATTRS TokenizeStoreIntFn GetTokenizeStoreIntFn( + int kind, Terminator &terminator, const char *which) { + switch (kind) { + case 1: + return &TokenizeStoreIntAt<1>; + case 2: + return &TokenizeStoreIntAt<2>; + case 4: + return &TokenizeStoreIntAt<4>; + case 8: + return &TokenizeStoreIntAt<8>; + case 16: + return &TokenizeStoreIntAt<16>; + default: + terminator.Crash( + "TOKENIZE: unsupported INTEGER kind=%d for %s", kind, which); + } +} + +template +static RT_API_ATTRS void TokenizeFillPositions(Descriptor &first, + Descriptor &last, const CHAR *str, std::size_t strChars, const CHAR *set, + std::size_t setChars, TokenizeStoreIntFn storeFirst, + TokenizeStoreIntFn storeLast, Terminator &terminator) { + + // Empty STRING should return one empty token, per Fortran standard. + if (strChars == 0) { + storeFirst(first, 0, 1); + storeLast(last, 0, 0); + return; + } + if (setChars == 0) { + storeFirst(first, 0, 1); + storeLast(last, 0, static_cast(strChars)); + return; + } + + std::size_t tokenIndex{0}; + std::size_t tokenStart{0}; + for (std::size_t pos{0}; pos < strChars; ++pos) { + if (TokenizeIsInSet(str[pos], set, setChars)) { + storeFirst(first, tokenIndex, static_cast(tokenStart + 1)); + storeLast(last, tokenIndex, static_cast(pos)); + ++tokenIndex; + tokenStart = pos + 1; + } + } + storeFirst(first, tokenIndex, static_cast(tokenStart + 1)); + storeLast(last, tokenIndex, static_cast(strChars)); + ++tokenIndex; + + // Sanity check: we should have filled exactly the allocated extent. + if (tokenIndex != static_cast(first.GetDimension(0).Extent())) { + terminator.Crash("TOKENIZE: internal error populating FIRST/LAST"); + } +} + +// Tokenize Form 1 implementation. +static RT_API_ATTRS void TokenizeImpl(Descriptor &tokens, Descriptor *separator, + const Descriptor &string, const Descriptor &set, Terminator &terminator) { + RUNTIME_CHECK(terminator, string.rank() == 0); + RUNTIME_CHECK(terminator, set.rank() == 0); + RUNTIME_CHECK(terminator, string.raw().type == set.raw().type); + RUNTIME_CHECK(terminator, tokens.rank() == 1); + RUNTIME_CHECK(terminator, tokens.IsAllocatable()); + if (separator) { + RUNTIME_CHECK(terminator, separator->rank() == 1); + RUNTIME_CHECK(terminator, separator->IsAllocatable()); + } + + switch (string.raw().type) { + case CFI_type_char: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes}; + std::size_t setChars{setBytes}; + const char *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + auto analysis{AnalyzeTokenize(str, strChars, setPtr, setChars)}; + TokenizeFillForm1(tokens, separator, string, str, strChars, setPtr, + setChars, analysis, terminator); + break; + } + case CFI_type_char16_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 1}; + std::size_t setChars{setBytes >> 1}; + const char16_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char16_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + auto analysis{AnalyzeTokenize(str, strChars, setPtr, setChars)}; + TokenizeFillForm1(tokens, separator, string, str, strChars, setPtr, + setChars, analysis, terminator); + break; + } + case CFI_type_char32_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 2}; + std::size_t setChars{setBytes >> 2}; + const char32_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char32_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + auto analysis{AnalyzeTokenize(str, strChars, setPtr, setChars)}; + TokenizeFillForm1(tokens, separator, string, str, strChars, setPtr, + setChars, analysis, terminator); + break; + } + default: + terminator.Crash("TOKENIZE: bad string type code %d", + static_cast(string.raw().type)); + } +} + +// Tokenize Form 2 implementation. +static RT_API_ATTRS void TokenizePositionsImpl(Descriptor &first, + Descriptor &last, const Descriptor &string, const Descriptor &set, + Terminator &terminator) { + RUNTIME_CHECK(terminator, string.rank() == 0); + RUNTIME_CHECK(terminator, set.rank() == 0); + RUNTIME_CHECK(terminator, string.raw().type == set.raw().type); + RUNTIME_CHECK(terminator, first.rank() == 1); + RUNTIME_CHECK(terminator, last.rank() == 1); + RUNTIME_CHECK(terminator, first.IsAllocatable()); + RUNTIME_CHECK(terminator, last.IsAllocatable()); + + auto firstCK{first.type().GetCategoryAndKind()}; + auto lastCK{last.type().GetCategoryAndKind()}; + if (!firstCK || firstCK->first != TypeCategory::Integer) { + terminator.Crash("TOKENIZE: FIRST is not an INTEGER array"); + } + if (!lastCK || lastCK->first != TypeCategory::Integer) { + terminator.Crash("TOKENIZE: LAST is not an INTEGER array"); + } + int firstKind{firstCK->second}; + int lastKind{lastCK->second}; + auto storeFirst{GetTokenizeStoreIntFn(firstKind, terminator, "FIRST")}; + auto storeLast{GetTokenizeStoreIntFn(lastKind, terminator, "LAST")}; + + // Count tokens. + std::size_t tokenCount{0}; + switch (string.raw().type) { + case CFI_type_char: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes}; + std::size_t setChars{setBytes}; + const char *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + tokenCount = AnalyzeTokenize(str, strChars, setPtr, setChars).tokenCount; + break; + } + case CFI_type_char16_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 1}; + std::size_t setChars{setBytes >> 1}; + const char16_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char16_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + tokenCount = AnalyzeTokenize(str, strChars, setPtr, setChars).tokenCount; + break; + } + case CFI_type_char32_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 2}; + std::size_t setChars{setBytes >> 2}; + const char32_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char32_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + tokenCount = AnalyzeTokenize(str, strChars, setPtr, setChars).tokenCount; + break; + } + default: + terminator.Crash("TOKENIZE: bad string type code %d", + static_cast(string.raw().type)); + } + + // (Re)allocate FIRST/LAST. + if (first.IsAllocated()) { + first.Deallocate(); + } + if (last.IsAllocated()) { + last.Deallocate(); + } + SubscriptValue extent[1]{static_cast(tokenCount)}; + first.Establish(TypeCategory::Integer, firstKind, nullptr, 1, extent, + CFI_attribute_allocatable); + first.GetDimension(0).SetBounds(1, extent[0]); + last.Establish(TypeCategory::Integer, lastKind, nullptr, 1, extent, + CFI_attribute_allocatable); + last.GetDimension(0).SetBounds(1, extent[0]); + if (first.Allocate(kNoAsyncObject) != CFI_SUCCESS) { + terminator.Crash("TOKENIZE: could not allocate FIRST array"); + } + if (last.Allocate(kNoAsyncObject) != CFI_SUCCESS) { + terminator.Crash("TOKENIZE: could not allocate LAST array"); + } + + if (tokenCount == 0) { + return; + } + + // Populate FIRST/LAST. + switch (string.raw().type) { + case CFI_type_char: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes}; + std::size_t setChars{setBytes}; + const char *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + TokenizeFillPositions(first, last, str, strChars, setPtr, setChars, + storeFirst, storeLast, terminator); + break; + } + case CFI_type_char16_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 1}; + std::size_t setChars{setBytes >> 1}; + const char16_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char16_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + TokenizeFillPositions(first, last, str, strChars, setPtr, setChars, + storeFirst, storeLast, terminator); + break; + } + case CFI_type_char32_t: { + std::size_t strBytes{string.ElementBytes()}; + std::size_t setBytes{set.ElementBytes()}; + std::size_t strChars{strBytes >> 2}; + std::size_t setChars{setBytes >> 2}; + const char32_t *str{ + strBytes == 0 ? nullptr : string.OffsetElement()}; + const char32_t *setPtr{ + setBytes == 0 ? nullptr : set.OffsetElement()}; + TokenizeFillPositions(first, last, str, strChars, setPtr, setChars, + storeFirst, storeLast, terminator); + break; + } + default: + break; + } +} + extern "C" { RT_EXT_API_GROUP_BEGIN @@ -938,6 +1359,22 @@ void RTDEF(CharacterMin)(Descriptor &accumulator, const Descriptor &x, MaxMin(accumulator, x, sourceFile, sourceLine); } +// TOKENIZE Form 1 entry point +void RTDEF(Tokenize)(Descriptor &tokens, Descriptor *separator, + const Descriptor &string, const Descriptor &set, const char *sourceFile, + int sourceLine) { + Terminator terminator{sourceFile, sourceLine}; + TokenizeImpl(tokens, separator, string, set, terminator); +} + +// TOKENIZE Form 2 entry point +void RTDEF(TokenizePositions)(Descriptor &first, Descriptor &last, + const Descriptor &string, const Descriptor &set, const char *sourceFile, + int sourceLine) { + Terminator terminator{sourceFile, sourceLine}; + TokenizePositionsImpl(first, last, string, set, terminator); +} + RT_EXT_API_GROUP_END } } // namespace Fortran::runtime diff --git a/flang-rt/unittests/Runtime/CharacterTest.cpp b/flang-rt/unittests/Runtime/CharacterTest.cpp index 5d8bcd2354c4c..4b304a98ada1b 100644 --- a/flang-rt/unittests/Runtime/CharacterTest.cpp +++ b/flang-rt/unittests/Runtime/CharacterTest.cpp @@ -431,6 +431,214 @@ TYPED_TEST(RepeatTests, Repeat) { } } +// Test TOKENIZE() - Form 1 and Form 2 +// Helper to create a scalar character descriptor from a raw C string. +template +OwningPtr CreateScalarDescriptor(const char *raw) { + std::size_t len{std::strlen(raw)}; + OwningPtr desc{Descriptor::Create( + sizeof(CHAR), len, nullptr, 0, nullptr, CFI_attribute_other)}; + if (desc->Allocate(kNoAsyncObject) != 0) { + return nullptr; + } + std::basic_string converted{raw, raw + len}; + std::copy(converted.begin(), converted.end(), desc->OffsetElement(0)); + return desc; +} + +// Helper to create an unallocated allocatable character descriptor (rank 1, +// deferred length) for TOKENS or SEPARATOR output. +template StaticDescriptor<1> CreateAllocatableCharDescriptor() { + StaticDescriptor<1> staticDesc; + Descriptor &desc{staticDesc.descriptor()}; + desc.Establish(static_cast(sizeof(CHAR)), static_cast(0), + nullptr, 1, nullptr, CFI_attribute_allocatable); + desc.GetDimension(0).SetBounds(1, 0); + return staticDesc; +} + +// Helper to create an unallocated allocatable integer descriptor (rank 1) +// for FIRST or LAST output. +static StaticDescriptor<1> CreateAllocatableIntDescriptor() { + StaticDescriptor<1> staticDesc; + Descriptor &desc{staticDesc.descriptor()}; + desc.Establish( + TypeCategory::Integer, 4, nullptr, 1, nullptr, CFI_attribute_allocatable); + desc.GetDimension(0).SetBounds(1, 0); + return staticDesc; +} + +// Helper to extract a token string from the TOKENS descriptor. +template +std::basic_string GetToken(Descriptor &tokens, std::size_t index) { + std::size_t elemBytes{tokens.ElementBytes()}; + std::size_t charLen{elemBytes / sizeof(CHAR)}; + const CHAR *data{tokens.OffsetElement(index * elemBytes)}; + return std::basic_string(data, charLen); +} + +template struct TokenizeTests : public ::testing::Test {}; +TYPED_TEST_SUITE(TokenizeTests, CharacterTypes, ); + +// Form 1: basic tokenization +TYPED_TEST(TokenizeTests, Form1Basic) { + auto string{CreateScalarDescriptor("first,second,third")}; + auto set{CreateScalarDescriptor(",")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto tokensStatic{CreateAllocatableCharDescriptor()}; + Descriptor &tokens{tokensStatic.descriptor()}; + + RTNAME(Tokenize)(tokens, nullptr, *string, *set); + + // Expect 3 tokens: "first", "second", "third" + ASSERT_TRUE(tokens.IsAllocated()); + EXPECT_EQ(tokens.GetDimension(0).Extent(), 3); + // Longest token is "second" (6 chars) + EXPECT_EQ(tokens.ElementBytes(), 6u * sizeof(TypeParam)); + + // Tokens are blank-padded to max length + std::basic_string t0{GetToken(tokens, 0)}; + std::basic_string t1{GetToken(tokens, 1)}; + std::basic_string t2{GetToken(tokens, 2)}; + std::basic_string e0{'f', 'i', 'r', 's', 't', ' '}; + std::basic_string e1{'s', 'e', 'c', 'o', 'n', 'd'}; + std::basic_string e2{'t', 'h', 'i', 'r', 'd', ' '}; + EXPECT_EQ(t0, e0); + EXPECT_EQ(t1, e1); + EXPECT_EQ(t2, e2); + tokens.Deallocate(); +} + +// Form 1: empty string produces one zero-length token +TYPED_TEST(TokenizeTests, Form1EmptyString) { + auto string{CreateScalarDescriptor("")}; + auto set{CreateScalarDescriptor(",")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto tokensStatic{CreateAllocatableCharDescriptor()}; + Descriptor &tokens{tokensStatic.descriptor()}; + + RTNAME(Tokenize)(tokens, nullptr, *string, *set); + + ASSERT_TRUE(tokens.IsAllocated()); + EXPECT_EQ(tokens.GetDimension(0).Extent(), 1) << "empty string = 1 token"; + EXPECT_EQ(tokens.ElementBytes(), 0u) << "token length should be 0"; + EXPECT_EQ(tokens.GetDimension(0).LowerBound(), 1); + tokens.Deallocate(); +} + +// Form 1: consecutive delimiters produce empty tokens +TYPED_TEST(TokenizeTests, Form1ConsecutiveDelimiters) { + auto string{CreateScalarDescriptor("a,,b")}; + auto set{CreateScalarDescriptor(",")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto tokensStatic{CreateAllocatableCharDescriptor()}; + Descriptor &tokens{tokensStatic.descriptor()}; + + RTNAME(Tokenize)(tokens, nullptr, *string, *set); + + ASSERT_TRUE(tokens.IsAllocated()); + // Expect 3 tokens: "a", "", "b" + EXPECT_EQ(tokens.GetDimension(0).Extent(), 3); + tokens.Deallocate(); +} + +// Form 1: with SEPARATOR output +TYPED_TEST(TokenizeTests, Form1WithSeparator) { + auto string{CreateScalarDescriptor("a,b;c")}; + auto set{CreateScalarDescriptor(",;")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto tokensStatic{CreateAllocatableCharDescriptor()}; + Descriptor &tokens{tokensStatic.descriptor()}; + auto sepStatic{CreateAllocatableCharDescriptor()}; + Descriptor &separator{sepStatic.descriptor()}; + + RTNAME(Tokenize)(tokens, &separator, *string, *set); + + // Expect 3 tokens: "a", "b", "c" + ASSERT_TRUE(tokens.IsAllocated()); + EXPECT_EQ(tokens.GetDimension(0).Extent(), 3); + ASSERT_TRUE(separator.IsAllocated()); + // Expect 2 separators: ',' then ';' + EXPECT_EQ(separator.GetDimension(0).Extent(), 2); + EXPECT_EQ(separator.ElementBytes(), sizeof(TypeParam)); + + // Check separator values: ',' then ';' + const TypeParam *sep0{separator.OffsetElement(0)}; + const TypeParam *sep1{ + separator.OffsetElement(separator.ElementBytes())}; + EXPECT_EQ(*sep0, static_cast(',')); + EXPECT_EQ(*sep1, static_cast(';')); + tokens.Deallocate(); + separator.Deallocate(); +} + +// Form 2: basic position output +TYPED_TEST(TokenizeTests, Form2Basic) { + // From the standard example: "first,second,,fourth" + auto string{CreateScalarDescriptor("first,second,,fourth")}; + auto set{CreateScalarDescriptor(",;")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto firstStatic{CreateAllocatableIntDescriptor()}; + Descriptor &first{firstStatic.descriptor()}; + auto lastStatic{CreateAllocatableIntDescriptor()}; + Descriptor &last{lastStatic.descriptor()}; + + RTNAME(TokenizePositions)(first, last, *string, *set); + + ASSERT_TRUE(first.IsAllocated()); + ASSERT_TRUE(last.IsAllocated()); + EXPECT_EQ(first.GetDimension(0).Extent(), 4); + EXPECT_EQ(last.GetDimension(0).Extent(), 4); + + // Expect: FIRST = [1, 7, 14, 15], LAST = [5, 12, 13, 20] + EXPECT_EQ(*first.OffsetElement(0 * sizeof(std::int32_t)), 1); + EXPECT_EQ(*first.OffsetElement(1 * sizeof(std::int32_t)), 7); + EXPECT_EQ(*first.OffsetElement(2 * sizeof(std::int32_t)), 14); + EXPECT_EQ(*first.OffsetElement(3 * sizeof(std::int32_t)), 15); + EXPECT_EQ(*last.OffsetElement(0 * sizeof(std::int32_t)), 5); + EXPECT_EQ(*last.OffsetElement(1 * sizeof(std::int32_t)), 12); + EXPECT_EQ(*last.OffsetElement(2 * sizeof(std::int32_t)), 13); + EXPECT_EQ(*last.OffsetElement(3 * sizeof(std::int32_t)), 20); + first.Deallocate(); + last.Deallocate(); +} + +// Form 2: empty string produces one token with FIRST=1, LAST=0 +TYPED_TEST(TokenizeTests, Form2EmptyString) { + auto string{CreateScalarDescriptor("")}; + auto set{CreateScalarDescriptor(",")}; + ASSERT_NE(string, nullptr); + ASSERT_NE(set, nullptr); + + auto firstStatic{CreateAllocatableIntDescriptor()}; + Descriptor &first{firstStatic.descriptor()}; + auto lastStatic{CreateAllocatableIntDescriptor()}; + Descriptor &last{lastStatic.descriptor()}; + + RTNAME(TokenizePositions)(first, last, *string, *set); + + ASSERT_TRUE(first.IsAllocated()); + ASSERT_TRUE(last.IsAllocated()); + EXPECT_EQ(first.GetDimension(0).Extent(), 1) << "empty string = 1 token"; + EXPECT_EQ(last.GetDimension(0).Extent(), 1); + + // Expect FIRST(1)=1, LAST(1)=0 + EXPECT_EQ(*first.OffsetElement(0), 1) << "FIRST(1) = 1"; + EXPECT_EQ(*last.OffsetElement(0), 0) << "LAST(1) = 0"; + first.Deallocate(); + last.Deallocate(); +} + // Test F_C_STRING() TEST(CharacterTests, FCString) { // Test 1: Default behavior (trim trailing blanks) diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index edc6d1bf8e252..753d475b4de52 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -447,6 +447,7 @@ struct IntrinsicLibrary { fir::ExtendedValue genTeamNumber(mlir::Type, llvm::ArrayRef); mlir::Value genTime(mlir::Type, llvm::ArrayRef); + void genTokenize(llvm::ArrayRef); mlir::Value genTrailz(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genTransfer(mlir::Type, llvm::ArrayRef); diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Character.h b/flang/include/flang/Optimizer/Builder/Runtime/Character.h index b7181e33d6887..684b7498e725a 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Character.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Character.h @@ -142,6 +142,22 @@ mlir::Value genVerify(fir::FirOpBuilder &builder, mlir::Location loc, int kind, mlir::Value setBase, mlir::Value setLen, mlir::Value back); +/// Generate call to TOKENIZE runtime (Form 1). +/// Splits \p stringBox into tokens based on separator characters in \p setBox. +/// \p tokensBox must be an unallocated allocatable array that receives the +/// token substrings. \p separatorBox is optional and receives separator chars. +void genTokenize(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value tokensBox, mlir::Value separatorBox, + mlir::Value stringBox, mlir::Value setBox); + +/// Generate call to TOKENIZE runtime (Form 2). +/// Returns token positions rather than substrings. +/// \p firstBox and \p lastBox must be unallocated allocatable integer arrays +/// that receive the starting and ending positions of each token. +void genTokenizePositions(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value firstBox, mlir::Value lastBox, + mlir::Value stringBox, mlir::Value setBox); + } // namespace fir::runtime #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CHARACTER_H diff --git a/flang/include/flang/Runtime/character.h b/flang/include/flang/Runtime/character.h index 36a66fc50e717..360418b7d5531 100644 --- a/flang/include/flang/Runtime/character.h +++ b/flang/include/flang/Runtime/character.h @@ -130,6 +130,13 @@ std::size_t RTDECL(Verify4)(const char32_t *, std::size_t, const char32_t *set, void RTDECL(Verify)(Descriptor &result, const Descriptor &string, const Descriptor &set, const Descriptor *back /*can be null*/, int kind, const char *sourceFile = nullptr, int sourceLine = 0); + +void RTDECL(Tokenize)(Descriptor &tokens, Descriptor *separator, + const Descriptor &string, const Descriptor &set, + const char *sourceFile = nullptr, int sourceLine = 0); +void RTDECL(TokenizePositions)(Descriptor &first, Descriptor &last, + const Descriptor &string, const Descriptor &set, + const char *sourceFile = nullptr, int sourceLine = 0); } } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_CHARACTER_H_ diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 9eaad6c049267..2ae1c478489c4 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -22,6 +22,7 @@ #include "flang/Support/Fortran.h" #include "llvm/Support/raw_ostream.h" #include +#include #include #include #include @@ -1749,6 +1750,26 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {{"seconds", AnyInt, Rank::scalar, Optionality::required, common::Intent::In}}, {}, Rank::elemental, IntrinsicClass::impureSubroutine}, + {"tokenize", + {{"string", SameCharNoLen, Rank::scalar, Optionality::required, + common::Intent::In}, + {"set", SameCharNoLen, Rank::scalar, Optionality::required, + common::Intent::In}, + {"tokens", SameCharNoLen, Rank::vector, Optionality::required, + common::Intent::Out}, + {"separator", SameCharNoLen, Rank::vector, Optionality::optional, + common::Intent::Out}}, + {}, Rank::elemental, IntrinsicClass::pureSubroutine}, + {"tokenize", + {{"string", SameCharNoLen, Rank::scalar, Optionality::required, + common::Intent::In}, + {"set", SameCharNoLen, Rank::scalar, Optionality::required, + common::Intent::In}, + {"first", AnyInt, Rank::vector, Optionality::required, + common::Intent::Out}, + {"last", AnyInt, Rank::vector, Optionality::required, + common::Intent::Out}}, + {}, Rank::elemental, IntrinsicClass::pureSubroutine}, {"unlink", {{"path", DefaultChar, Rank::scalar, Optionality::required, common::Intent::In}, @@ -3704,6 +3725,24 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) { arg ? arg->sourceLocation() : context.messages().at(), "Argument of LOC() must be an object or procedure"_err_en_US); } + } else if (name == "tokenize") { + // Both forms of TOKENIZE have at least 4 dummy arguments, and the last two + // must be allocatable. + const auto &dummies{ + call.specificIntrinsic.characteristics.value().dummyArguments}; + for (int i{2}; i < 4; ++i) { + const auto &arg{call.arguments[i]}; + if (arg) { + if (const auto *expr{arg->UnwrapExpr()}) { + if (!IsAllocatableDesignator(*expr)) { + ok = false; + context.messages().Say(arg->sourceLocation(), + "'%s=' argument to 'tokenize' must be ALLOCATABLE"_err_en_US, + dummies[i].name); + } + } + } + } } return ok; } @@ -3766,15 +3805,81 @@ std::optional IntrinsicProcTable::Implementation::Probe( } } + // Find the specific subroutine and match the actual arguments against its + // dummy argument patterns. If there are multiple specific subroutines with + // the same name, try them in order. If one matches, clear out the errors. + // If none match, keep the messages from the form whose dummy argument + // types and keywords best match the actual arguments supplied. if (call.isSubroutineCall) { const std::string &name{ResolveAlias(call.name)}; auto subrRange{subroutines_.equal_range(name)}; + parser::Messages subrErrors; + int bestScore{INT_MIN}; + parser::Messages localBuffer; + parser::Messages *finalBuffer{context.messages().messages()}; + parser::ContextualMessages localMessages{ + context.messages().at(), finalBuffer ? &localBuffer : nullptr}; + FoldingContext localContext{context, localMessages}; for (auto iter{subrRange.first}; iter != subrRange.second; ++iter) { if (auto specificCall{iter->second->Match( - call, defaults_, arguments, context, builtinsScope_)}) { + call, defaults_, arguments, localContext, builtinsScope_)}) { + if (finalBuffer) { + finalBuffer->Annex(std::move(localBuffer)); + } ApplySpecificChecks(*specificCall, context); return specificCall; } + // Match failed. Compute a score reflecting how well the actual + // arguments correspond to this form's dummy arguments: count the + // number of positional arguments whose type category matches the + // corresponding dummy's expected categories, plus the number of + // keyword arguments whose keyword name matches a dummy in this form, + // minus the number of required dummies that cannot be satisfied by + // the number of arguments provided. Keep the error messages from + // the form with the highest score, preferring an earlier form on + // ties. + const auto *iface{iter->second}; + int dummyCount{iface->CountArguments()}; + int numRequired{0}; + for (int j{0}; j < dummyCount; ++j) { + if (iface->dummy[j].optionality == Optionality::required) { + ++numRequired; + } + } + int score{0}; + int positionalIndex{0}; + for (const auto &arg : arguments) { + if (arg) { + if (auto kw{arg->keyword()}) { + for (int k{0}; k < dummyCount; ++k) { + if (kw == iface->dummy[k].keyword) { + ++score; + break; + } + } + } else { + if (positionalIndex < dummyCount) { + if (auto type{arg->GetType()}) { + if (iface->dummy[positionalIndex].typePattern.categorySet.test( + type->category())) { + ++score; + } + } + } + ++positionalIndex; + } + } + } + score -= std::max(0, numRequired - static_cast(arguments.size())); + if (score > bestScore) { + bestScore = score; + subrErrors = std::move(localBuffer); + } else { + localBuffer.clear(); + } + } + if (finalBuffer) { + finalBuffer->Annex(std::move(subrErrors)); } if (IsIntrinsicFunction(call.name) && !IsDualIntrinsic(call.name)) { context.messages().Say( diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index f71ef0f12c992..090236fe3e5c6 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -797,6 +797,13 @@ static constexpr IntrinsicHandler handlers[]{ {"team", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, {"time", &I::genTime, {}, /*isElemental=*/false}, + {"tokenize", + &I::genTokenize, + {{{"string", asAddr}, + {"set", asAddr}, + {"out1", asInquired}, + {"out2", asInquired, handleDynamicOptional}}}, + /*isElemental=*/false}, {"trailz", &I::genTrailz}, {"transfer", &I::genTransfer, @@ -8529,6 +8536,101 @@ void IntrinsicLibrary::genSleep(llvm::ArrayRef args) { fir::runtime::genSleep(builder, loc, fir::getBase(args[0])); } +// TOKENIZE +void IntrinsicLibrary::genTokenize(llvm::ArrayRef args) { + assert(args.size() == 4 && "TOKENIZE requires 3 or 4 arguments"); + + const fir::ExtendedValue &string = args[0]; + const fir::ExtendedValue &set = args[1]; + + // Distinguish forms by the element type of the third argument. For form 1, + // TOKENS is CHARACTER. For form 2, FIRST is INTEGER. + mlir::Type thirdArgEleTy = fir::getElementTypeOf(args[2]); + bool isForm1 = fir::isa_char(thirdArgEleTy); + bool isForm2 = fir::isa_integer(thirdArgEleTy); + assert((isForm1 || isForm2) && + "TOKENIZE third argument must be CHARACTER or INTEGER"); + + mlir::Value stringBox = builder.createBox(loc, string); + mlir::Value setBox = builder.createBox(loc, set); + + mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); + mlir::Type boxNoneRefTy = fir::ReferenceType::get(boxNoneTy); + + // A lambda to return the address of the descriptor storage to pass to the + // runtime. For MutableBoxValue, this also handles any required syncing + // before/after the runtime call. + auto getBoxStorageAddr = + [&](const fir::ExtendedValue &exv, llvm::StringRef what, + const fir::MutableBoxValue **mutableBoxOut) -> mlir::Value { + if (const auto *mb = exv.getBoxOf()) { + if (mutableBoxOut) + *mutableBoxOut = mb; + mlir::Value addr = fir::factory::getMutableIRBox(builder, loc, *mb); + return builder.createConvert(loc, boxNoneRefTy, addr); + } + if (const auto *bv = exv.getBoxOf()) { + mlir::Value addr = bv->getAddr(); + if (auto boxTy = fir::dyn_cast_ptrEleTy(addr.getType())) { + if (mlir::isa(boxTy)) + return builder.createConvert(loc, boxNoneRefTy, addr); + } + fir::emitFatalError(loc, llvm::Twine("TOKENIZE: ") + what + + " must be a descriptor address"); + } + fir::emitFatalError(loc, llvm::Twine("TOKENIZE: ") + what + + " not lowered as a boxed entity"); + }; + + if (isForm1) { + // Form 1: TOKENIZE(STRING, SET, TOKENS [, SEPARATOR]) + const fir::ExtendedValue &tokens = args[2]; + const fir::MutableBoxValue *tokensMutableBox{nullptr}; + mlir::Value tokensBoxAddr = + getBoxStorageAddr(tokens, "TOKENS", &tokensMutableBox); + + // Handle optional SEPARATOR argument + mlir::Value separatorBoxAddr; + const fir::MutableBoxValue *separatorMutableBox{nullptr}; + if (!isStaticallyAbsent(args[3])) { + const fir::ExtendedValue &separator = args[3]; + separatorBoxAddr = + getBoxStorageAddr(separator, "SEPARATOR", &separatorMutableBox); + } else { + separatorBoxAddr = builder.createNullConstant(loc, boxNoneRefTy); + } + + // Call the Form 1 runtime function + fir::runtime::genTokenize(builder, loc, tokensBoxAddr, separatorBoxAddr, + stringBox, setBox); + + if (tokensMutableBox) + fir::factory::syncMutableBoxFromIRBox(builder, loc, *tokensMutableBox); + if (separatorMutableBox) + fir::factory::syncMutableBoxFromIRBox(builder, loc, *separatorMutableBox); + + } else { + // Form 2: TOKENIZE(STRING, SET, FIRST, LAST) + const fir::ExtendedValue &first = args[2]; + const fir::ExtendedValue &last = args[3]; + + const fir::MutableBoxValue *firstMutableBox{nullptr}; + const fir::MutableBoxValue *lastMutableBox{nullptr}; + mlir::Value firstBoxAddr = + getBoxStorageAddr(first, "FIRST", &firstMutableBox); + mlir::Value lastBoxAddr = getBoxStorageAddr(last, "LAST", &lastMutableBox); + + // Call the Form 2 runtime function + fir::runtime::genTokenizePositions(builder, loc, firstBoxAddr, lastBoxAddr, + stringBox, setBox); + + if (firstMutableBox) + fir::factory::syncMutableBoxFromIRBox(builder, loc, *firstMutableBox); + if (lastMutableBox) + fir::factory::syncMutableBoxFromIRBox(builder, loc, *lastMutableBox); + } +} + // TRANSFER fir::ExtendedValue IntrinsicLibrary::genTransfer(mlir::Type resultType, diff --git a/flang/lib/Optimizer/Builder/Runtime/Character.cpp b/flang/lib/Optimizer/Builder/Runtime/Character.cpp index e297125880f7a..28e795b8de759 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Character.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Character.cpp @@ -285,6 +285,35 @@ void fir::runtime::genVerifyDescriptor(fir::FirOpBuilder &builder, kind); } +void fir::runtime::genTokenize(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value tokensBox, mlir::Value separatorBox, + mlir::Value stringBox, mlir::Value setBox) { + auto func = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getFunctionType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, tokensBox, separatorBox, + stringBox, setBox, sourceFile, sourceLine); + fir::CallOp::create(builder, loc, func, args); +} + +void fir::runtime::genTokenizePositions( + fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value firstBox, + mlir::Value lastBox, mlir::Value stringBox, mlir::Value setBox) { + auto func = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getFunctionType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, firstBox, lastBox, + stringBox, setBox, sourceFile, sourceLine); + fir::CallOp::create(builder, loc, func, args); +} + mlir::Value fir::runtime::genVerify(fir::FirOpBuilder &builder, mlir::Location loc, int kind, mlir::Value stringBase, diff --git a/flang/test/Lower/Intrinsics/tokenize.f90 b/flang/test/Lower/Intrinsics/tokenize.f90 new file mode 100644 index 0000000000000..ef533794a5a30 --- /dev/null +++ b/flang/test/Lower/Intrinsics/tokenize.f90 @@ -0,0 +1,27 @@ +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: tok_form1 +subroutine tok_form1() + implicit none + character(:), allocatable :: tokens(:) + call tokenize("a,b", ",", tokens) + ! CHECK-DAG: %[[TOKENS:.*]] = fir.alloca !fir.box>>> + ! CHECK-DAG: %[[TOKENS_DECL:.*]]:2 = hlfir.declare %[[TOKENS]] {fortran_attrs = #fir.var_attrs + ! CHECK-DAG: %[[TOKENS_NONE:.*]] = fir.convert %[[TOKENS_DECL]]#0 : (!fir.ref>>>>) -> !fir.ref> + ! CHECK-DAG: %[[SEP_NONE:.*]] = fir.zero_bits !fir.ref> + ! CHECK: fir.call @_FortranATokenize(%[[TOKENS_NONE]], %[[SEP_NONE]], +end subroutine tok_form1 + +! CHECK-LABEL: tok_form2 +subroutine tok_form2() + implicit none + integer, allocatable :: first(:), last(:) + call tokenize("a,,b", ",", first, last) + ! CHECK-DAG: %[[FIRST:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[LAST:.*]] = fir.alloca !fir.box>> + ! CHECK-DAG: %[[FIRST_DECL:.*]]:2 = hlfir.declare %[[FIRST]] {fortran_attrs = #fir.var_attrs + ! CHECK-DAG: %[[LAST_DECL:.*]]:2 = hlfir.declare %[[LAST]] {fortran_attrs = #fir.var_attrs + ! CHECK-DAG: %[[FIRST_NONE:.*]] = fir.convert %[[FIRST_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> + ! CHECK-DAG: %[[LAST_NONE:.*]] = fir.convert %[[LAST_DECL]]#0 : (!fir.ref>>>) -> !fir.ref> + ! CHECK: fir.call @_FortranATokenizePositions(%[[FIRST_NONE]], %[[LAST_NONE]], +end subroutine tok_form2 diff --git a/flang/test/Semantics/tokenize-errors.f90 b/flang/test/Semantics/tokenize-errors.f90 new file mode 100644 index 0000000000000..204894817e904 --- /dev/null +++ b/flang/test/Semantics/tokenize-errors.f90 @@ -0,0 +1,267 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Check for semantic errors in tokenize() subroutine calls +! Based on Fortran 2023 standard requirements + +program test_tokenize_errors + implicit none + + ! Valid declarations for reference + character(:), allocatable :: tokens(:), separator(:) + integer, allocatable :: first(:), last(:) + character(20) :: string + character(5) :: set + + ! Invalid declarations for testing + integer :: int_scalar, int_array(10) + real :: real_scalar + character(10) :: fixed_tokens(10), fixed_separator(10) + integer :: fixed_first(10), fixed_last(10) + character(10) :: string_array(5) + character(5) :: set_array(5) + character(len=10, kind=2) :: wide_string, wide_set + character(len=10, kind=2), allocatable :: wide_tokens(:) + real, allocatable :: real_first(:), real_last(:) + logical, allocatable :: logical_array(:) + integer, allocatable :: first_2d(:,:), last_2d(:,:) + character(:), allocatable :: tokens_2d(:,:) + + type t_coarray + integer, allocatable :: a(:) + end type + type(t_coarray) :: coa[*] + integer, allocatable :: coindexed_first(:)[:] + integer, allocatable :: coindexed_last(:)[:] + character(:), allocatable :: coindexed_tokens(:)[:] + + !======================================================================== + ! Test Form 1: TOKENIZE(STRING, SET, TOKENS [, SEPARATOR]) + !======================================================================== + + ! Valid call (reference) + call tokenize("hello world", " ", tokens) + call tokenize(string, set, tokens, separator) + + !======================================================================== + ! Form 1: Wrong types for STRING argument + !======================================================================== + + !ERROR: Actual argument for 'string=' has bad type 'INTEGER(4)' + call tokenize(int_scalar, set, tokens) + + !ERROR: Actual argument for 'string=' has bad type 'REAL(4)' + call tokenize(real_scalar, set, tokens) + + !======================================================================== + ! Form 1: Wrong rank for STRING (must be scalar) + !======================================================================== + ! Fails + !ERROR: 'string=' argument has unacceptable rank 1 + call tokenize(string_array, set, tokens) + + !======================================================================== + ! Form 1: Wrong types for SET argument + !======================================================================== + + !ERROR: Actual argument for 'set=' has bad type 'INTEGER(4)' + call tokenize(string, int_scalar, tokens) + + !ERROR: Actual argument for 'set=' has bad type 'REAL(4)' + call tokenize(string, real_scalar, tokens) + + !======================================================================== + ! Form 1: Wrong rank for SET (must be scalar) + !======================================================================== + ! Fails + !ERROR: 'set=' argument has unacceptable rank 1 + call tokenize(string, set_array, tokens) + + !======================================================================== + ! Form 1: Wrong types for TOKENS argument + !======================================================================== + ! Fails + !ERROR: Actual argument for 'tokens=' has bad type 'INTEGER(4)' + call tokenize(string, set, int_array) + ! Fails + !ERROR: Actual argument for 'tokens=' has bad type 'REAL(4)' + call tokenize(string, set, real_first) + ! Fails + !ERROR: Actual argument for 'tokens=' has bad type 'LOGICAL(4)' + call tokenize(string, set, logical_array) + + !======================================================================== + ! Form 1: Wrong rank for TOKENS (must be rank-1 array) + !======================================================================== + ! Fails + !ERROR: 'tokens=' argument has unacceptable rank 0 + call tokenize(string, set, string) + ! Fails + !ERROR: 'tokens=' argument has unacceptable rank 2 + call tokenize(string, set, tokens_2d) + + !======================================================================== + ! Form 1: TOKENS must be allocatable + !======================================================================== + + !ERROR: 'tokens=' argument to 'tokenize' must be ALLOCATABLE + call tokenize(string, set, fixed_tokens) + + !======================================================================== + ! Form 1: Wrong types for optional SEPARATOR argument + !======================================================================== + ! Fails + !ERROR: Actual argument for 'separator=' has bad type 'INTEGER(4)' + call tokenize(string, set, tokens, int_array) + ! Fails + !ERROR: Actual argument for 'separator=' has bad type 'REAL(4)' + call tokenize(string, set, tokens, real_first) + + !======================================================================== + ! Form 1: Wrong rank for SEPARATOR (must be rank-1 array) + !======================================================================== + ! Fails + !ERROR: 'separator=' argument has unacceptable rank 0 + call tokenize(string, set, tokens, set) + + !======================================================================== + ! Form 1: SEPARATOR must be allocatable + !======================================================================== + + !ERROR: 'separator=' argument to 'tokenize' must be ALLOCATABLE + call tokenize(string, set, tokens, fixed_separator) + + !======================================================================== + ! Form 1: Character kind mismatches + !======================================================================== + ! Fails + ! wide_string (kind=2) becomes sameArg; set (kind=1) fails sameKind check + !ERROR: Actual argument for 'set=' has bad type or kind 'CHARACTER(KIND=1,LEN=5_8)' + call tokenize(wide_string, set, tokens) + ! Fails + !ERROR: Actual argument for 'set=' has bad type or kind 'CHARACTER(KIND=2,LEN=10_8)' + call tokenize(string, wide_set, tokens) + ! Fails + !ERROR: Actual argument for 'tokens=' has bad type or kind 'CHARACTER(KIND=2,LEN=10_8)' + call tokenize(string, set, wide_tokens) + + !======================================================================== + ! Test Form 2: TOKENIZE(STRING, SET, FIRST, LAST) + !======================================================================== + + ! Valid call (reference) + call tokenize("hello world", " ", first, last) + + !======================================================================== + ! Form 2: Wrong types for STRING argument (same as Form 1) + !======================================================================== + + !ERROR: Actual argument for 'string=' has bad type 'INTEGER(4)' + call tokenize(int_scalar, set, first, last) + + !======================================================================== + ! Form 2: Wrong types for SET argument (same as Form 1) + !======================================================================== + + !ERROR: Actual argument for 'set=' has bad type 'INTEGER(4)' + call tokenize(string, int_scalar, first, last) + + !======================================================================== + ! Form 2: Wrong types for FIRST argument + !======================================================================== + + !ERROR: Actual argument for 'first=' has bad type 'REAL(4)' + call tokenize(string, set, real_first, last) + + !ERROR: Actual argument for 'first=' has bad type 'LOGICAL(4)' + call tokenize(string, set, logical_array, last) + + !======================================================================== + ! Form 2: Wrong rank for FIRST (must be rank-1 array) + !======================================================================== + + !ERROR: 'first=' argument has unacceptable rank 0 + call tokenize(string, set, int_scalar, last) + + !ERROR: 'first=' argument has unacceptable rank 2 + call tokenize(string, set, first_2d, last) + + !======================================================================== + ! Form 2: FIRST must be allocatable + !======================================================================== + + !ERROR: 'first=' argument to 'tokenize' must be ALLOCATABLE + call tokenize(string, set, fixed_first, last) + + !======================================================================== + ! Form 2: Wrong types for LAST argument + !======================================================================== + + !ERROR: Actual argument for 'last=' has bad type 'REAL(4)' + call tokenize(string, set, first, real_first) + + !======================================================================== + ! Form 2: Wrong rank for LAST (must be rank-1 array) + !======================================================================== + + !ERROR: 'last=' argument has unacceptable rank 0 + call tokenize(string, set, first, int_scalar) + + !ERROR: 'last=' argument has unacceptable rank 2 + call tokenize(string, set, first, last_2d) + + !======================================================================== + ! Form 2: LAST must be allocatable + !======================================================================== + + !ERROR: 'last=' argument to 'tokenize' must be ALLOCATABLE + call tokenize(string, set, first, fixed_last) + + !======================================================================== + ! Argument count errors + !======================================================================== + + !ERROR: missing mandatory 'set=' argument + call tokenize(string) + ! Fails + !ERROR: missing mandatory 'tokens=' argument + call tokenize(string, set) + + !ERROR: too many actual arguments for intrinsic 'tokenize' + call tokenize(string, set, tokens, separator, first) + + !======================================================================== + ! Coindexed object restrictions (if applicable) + !======================================================================== + + ! Note: Coarray tests depend on whether the standard allows coindexed + ! objects for TOKENIZE. Uncomment if compiler version enforces this. + + ! !ERROR: 'first=' argument to 'tokenize' may not be a coindexed object + ! call tokenize(string, set, coindexed_first[1], last) + + ! !ERROR: 'last=' argument to 'tokenize' may not be a coindexed object + ! call tokenize(string, set, first, coindexed_last[1]) + + ! !ERROR: 'tokens=' argument to 'tokenize' may not be a coindexed object + ! call tokenize(string, set, coindexed_tokens[1]) + + !======================================================================== + ! Keyword argument errors + !======================================================================== + + !ERROR: unknown keyword argument to intrinsic 'tokenize' + call tokenize(string, set, tokens, invalid_keyword=separator) + ! Fails + !ERROR: Actual argument for 'tokens=' has bad type 'INTEGER(4)' + call tokenize(string=string, set=set, tokens=first, separator=separator) + + !======================================================================== + ! Type/kind inconsistency between STRING, SET, TOKENS, SEPARATOR + !======================================================================== + + ! All character arguments must have the same kind (but can have different lengths) + ! This is implicitly handled by SameCharNoLen in the intrinsic definition + ! Fails + !ERROR: Actual argument for 'set=' has bad type or kind 'CHARACTER(KIND=2,LEN=10_8)' + call tokenize(string=string, set=wide_set, tokens=tokens) + +end program test_tokenize_errors From 48eb40bee0248423fd6175ecd192ab15a71fb27b Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 27 Feb 2026 10:47:11 -0800 Subject: [PATCH 25/58] [lldb-dap] Adjust VariableReferenceStorage lifetime management. (#183176) Adjusting `VariableReferenceStorage` to only need to track permanent vs temporary storage by making `VariableStore` the common base class. Moved the subclasses of `VariableStore` into the Variables.cpp file, since they're no long referenced externally. Expanding on the tests by adding an updated core dump with variables in the argument scope we can use to validate variable storage. --- .../test/tools/lldb-dap/dap_server.py | 14 +- .../lldb-dap/variables/TestDAP_variables.py | 22 +- .../children/TestDAP_variables_children.py | 16 +- .../Handler/EvaluateRequestHandler.cpp | 4 +- .../lldb-dap/Handler/ScopesRequestHandler.cpp | 3 +- .../Handler/SetVariableRequestHandler.cpp | 2 +- .../Handler/VariablesRequestHandler.cpp | 9 +- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 4 +- lldb/tools/lldb-dap/SBAPIExtras.h | 48 +- lldb/tools/lldb-dap/Variables.cpp | 512 ++++++----- lldb/tools/lldb-dap/Variables.h | 89 +- lldb/unittests/DAP/DAPTypesTest.cpp | 20 +- .../DAP/Inputs/linux-x86_64.core.yaml | 867 +++++++++++++++++- .../DAP/Inputs/linux-x86_64.out.yaml | 630 +++++++++++-- lldb/unittests/DAP/VariablesTest.cpp | 124 ++- 15 files changed, 1854 insertions(+), 510 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index e8fd8e8e37e65..b8aee69bbd281 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -125,6 +125,7 @@ class Breakpoint(TypedDict, total=False): def is_verified(src: "Breakpoint") -> bool: return src.get("verified", False) + def dump_dap_log(log_file: Optional[str]) -> None: print("========= DEBUG ADAPTER PROTOCOL LOGS =========", file=sys.stderr) if log_file is None: @@ -769,12 +770,13 @@ def get_scope_variables(self, scope_name, frameIndex=0, threadId=None, is_hex=No if scope["name"] == scope_name: varRef = scope["variablesReference"] variables_response = self.request_variables(varRef, is_hex=is_hex) - if variables_response: - if "body" in variables_response: - body = variables_response["body"] - if "variables" in body: - vars = body["variables"] - return vars + if not variables_response["success"]: + return variables_response + if variables_response and "body" in variables_response: + body = variables_response["body"] + if "variables" in body: + vars = body["variables"] + return vars return [] def get_global_variables(self, frameIndex=0, threadId=None): diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py index 7abcec56a7880..911d8384c2a70 100644 --- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py +++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py @@ -133,21 +133,13 @@ def darwin_dwarf_missing_obj(self, initCommands): self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint") self.continue_to_breakpoints(breakpoint_ids) - locals = self.dap_server.get_local_variables() - - verify_locals = { - "": { - "equals": {"type": "const char *"}, - "contains": { - "value": [ - "debug map object file ", - 'main.o" containing debug info does not exist, debug info will not be loaded', - ] - }, - }, - } - varref_dict = {} - self.verify_variables(verify_locals, locals, varref_dict) + resp = self.dap_server.get_local_variables() + self.assertFalse(resp["success"], "Expected to fail") + self.assertEqual( + f'debug map object file "{main_obj}" containing debug info does not exist, debug info will not be loaded', + resp["body"]["error"]["format"], + ) + self.assertTrue(resp["body"]["error"]["showUser"]) def do_test_scopes_variables_setVariable_evaluate( self, enableAutoVariableSummaries: bool diff --git a/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py b/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py index d288f0de028a7..7806f3817ef57 100644 --- a/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py +++ b/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py @@ -38,7 +38,7 @@ def test_get_num_children(self): )["body"]["result"], ) - @skipIf(archs=["arm$", "arm64", "aarch64"]) + @expectedFailureAll(archs=["arm$", "aarch64"]) def test_return_variable_with_children(self): """ Test the stepping out of a function with return value show the children correctly @@ -62,16 +62,12 @@ def test_return_variable_with_children(self): local_variables = self.dap_server.get_local_variables() - # verify has return variable as local - result_variable = list( - filter( - lambda val: val.get("name") == "(Return Value)", local_variables - ) - ) - self.assertEqual(len(result_variable), 1) - result_variable = result_variable[0] + # Verify return value is the first item in as locals. + self.assertIsNot(len(local_variables), 0) + return_variable = local_variables[0] + self.assertEqual(return_variable["name"], "(Return Value)") - result_var_ref = result_variable.get("variablesReference") + result_var_ref = return_variable.get("variablesReference") self.assertIsNot(result_var_ref, None, "There is no result value") result_value = self.dap_server.request_variables(result_var_ref) diff --git a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp index 77d9f03554a2a..f2117d81f315c 100644 --- a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp @@ -133,8 +133,8 @@ EvaluateRequestHandler::Run(const EvaluateArguments &arguments) const { body.type = desc.display_type_name; if (value.MightHaveChildren() || ValuePointsToCode(value)) - body.variablesReference = dap.reference_storage.InsertVariable( - value, /*is_permanent=*/is_repl_context); + body.variablesReference = + dap.reference_storage.Insert(value, /*is_permanent=*/is_repl_context); if (lldb::addr_t addr = value.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS) body.memoryReference = EncodeMemoryReference(addr); diff --git a/lldb/tools/lldb-dap/Handler/ScopesRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ScopesRequestHandler.cpp index 3786d583e0e87..b2b006baf8a5e 100644 --- a/lldb/tools/lldb-dap/Handler/ScopesRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ScopesRequestHandler.cpp @@ -36,8 +36,7 @@ ScopesRequestHandler::Run(const ScopesArguments &args) const { frame.GetThread().SetSelectedFrame(frame.GetFrameID()); } - std::vector scopes = - dap.reference_storage.CreateScopes(frame); + std::vector scopes = dap.reference_storage.Insert(frame); return ScopesResponseBody{std::move(scopes)}; } diff --git a/lldb/tools/lldb-dap/Handler/SetVariableRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetVariableRequestHandler.cpp index 725d5de094c95..8fe424b55c9b1 100644 --- a/lldb/tools/lldb-dap/Handler/SetVariableRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/SetVariableRequestHandler.cpp @@ -67,7 +67,7 @@ SetVariableRequestHandler::Run(const SetVariableArguments &args) const { // is_permanent is false because debug console does not support // setVariable request. const var_ref_t new_var_ref = - dap.reference_storage.InsertVariable(variable, /*is_permanent=*/false); + dap.reference_storage.Insert(variable, /*is_permanent=*/false); if (variable.MightHaveChildren()) { body.variablesReference = new_var_ref; if (desc.type_obj.IsArrayType()) diff --git a/lldb/tools/lldb-dap/Handler/VariablesRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/VariablesRequestHandler.cpp index 26719b3a14d4d..7918be4983cc0 100644 --- a/lldb/tools/lldb-dap/Handler/VariablesRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/VariablesRequestHandler.cpp @@ -13,7 +13,6 @@ #include "Protocol/DAPTypes.h" #include "Protocol/ProtocolRequests.h" #include "Variables.h" -#include "llvm/Support/ErrorExtras.h" using namespace llvm; using namespace lldb_dap::protocol; @@ -38,8 +37,12 @@ VariablesRequestHandler::Run(const VariablesArguments &arguments) const { llvm::formatv("invalid variablesReference: {}.", var_ref.AsUInt32()), /*error_code=*/llvm::inconvertibleErrorCode(), /*show_user=*/false); - return VariablesResponseBody{ - store->GetVariables(dap.reference_storage, dap.configuration, arguments)}; + Expected> variables = + store->GetVariables(dap.reference_storage, dap.configuration, arguments); + if (llvm::Error err = variables.takeError()) + return err; + + return VariablesResponseBody{*variables}; } } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 5c5d279656d83..5564489cf2e69 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -28,8 +28,7 @@ namespace lldb_dap::protocol { enum ReferenceKind : uint8_t { eReferenceKindTemporary = 0, eReferenceKindPermanent = 1, - eReferenceKindScope = 1 << 1, - eReferenceKindInvalid = 0xFF + eReferenceKindInvalid = 0xFF, }; /// The var_ref_t hold two values, the `ReferenceKind` and the @@ -63,7 +62,6 @@ struct var_ref_t { switch (current_kind) { case eReferenceKindTemporary: case eReferenceKindPermanent: - case eReferenceKindScope: return current_kind; default: return eReferenceKindInvalid; diff --git a/lldb/tools/lldb-dap/SBAPIExtras.h b/lldb/tools/lldb-dap/SBAPIExtras.h index 2f7a18d1a3da1..f56d20d9c3134 100644 --- a/lldb/tools/lldb-dap/SBAPIExtras.h +++ b/lldb/tools/lldb-dap/SBAPIExtras.h @@ -14,25 +14,43 @@ #include "lldb/API/SBThread.h" #include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBValue.h" +#include "lldb/API/SBValueList.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/raw_ostream.h" #include #include +#include namespace lldb { /// An iterator helper for iterating over various SB API containers. -template -struct iter { - using difference_type = Index; - using value_type = Item; +template +class iter + : public llvm::iterator_facade_base, + std::random_access_iterator_tag, Item, + Index> { +public: + iter(const Container &container, Index index) + : container(container), index(index) {} + Item operator*() { return std::invoke(Get, container, index); } + Item operator*() const { return std::invoke(Get, container, index); } + iter &operator+=(Index N) { + index += N; + return *this; + } + iter &operator-=(Index N) { + index -= N; + return *this; + } + Index operator-(const iter &other) const { return index - other.index; } + bool operator==(const iter &other) const { return index == other.index; } + bool operator!=(const iter &other) const { return !(*this == other); } + bool operator<(const iter &other) const { return index < other.index; } + +private: Container container; Index index; - - Item operator*() { return std::invoke(Get, container, index); } - void operator++() { index++; } - bool operator!=(const iter &other) { return index != other.index; } }; /// SBProcess thread iterator. @@ -57,11 +75,21 @@ inline frame_iter end(SBThread T) { return {T, T.GetNumFrames()}; } /// SBValue value iterators. /// @{ -using value_iter = iter; +using value_iter = iter( + &SBValue::GetChildAtIndex)>; inline value_iter begin(SBValue &T) { return {T, 0}; } inline value_iter end(SBValue &T) { return {T, T.GetNumChildren()}; } /// @} +/// SBValue value iterators. +/// @{ +using value_list_iter = + iter; +inline value_list_iter begin(SBValueList &T) { return {T, 0}; } +inline value_list_iter end(SBValueList &T) { return {T, T.GetSize()}; } +/// @} + // llvm::raw_ostream print helpers. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SBStream &stream) { diff --git a/lldb/tools/lldb-dap/Variables.cpp b/lldb/tools/lldb-dap/Variables.cpp index 1f429b087ac0e..50e79b0f04b93 100644 --- a/lldb/tools/lldb-dap/Variables.cpp +++ b/lldb/tools/lldb-dap/Variables.cpp @@ -1,4 +1,4 @@ -//===-- Variables.cpp ---------------------------------------------------*-===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,303 +9,321 @@ #include "Variables.h" #include "DAPLog.h" #include "JSONUtils.h" +#include "LLDBUtils.h" #include "Protocol/DAPTypes.h" #include "Protocol/ProtocolRequests.h" #include "Protocol/ProtocolTypes.h" #include "ProtocolUtils.h" #include "SBAPIExtras.h" +#include "lldb/API/SBDeclaration.h" #include "lldb/API/SBFrame.h" -#include "lldb/API/SBProcess.h" #include "lldb/API/SBValue.h" #include "lldb/API/SBValueList.h" +#include "lldb/lldb-types.h" #include "llvm/ADT/Sequence.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" #include #include #include +using namespace llvm; using namespace lldb_dap; using namespace lldb_dap::protocol; -namespace lldb_dap { +namespace { -protocol::Scope CreateScope(ScopeKind kind, var_ref_t variablesReference, - bool expensive) { - protocol::Scope scope; - scope.variablesReference = variablesReference; - scope.expensive = expensive; +bool HasInnerVarref(lldb::SBValue &v) { + return v.MightHaveChildren() || ValuePointsToCode(v) || + v.GetDeclaration().IsValid(); +} - // TODO: Support "arguments" and "return value" scope. - // At the moment lldb-dap includes the arguments and return_value into the - // "locals" scope. - // VS Code only expands the first non-expensive scope. This causes friction - // if we add the arguments above the local scope, as the locals scope will not - // be expanded if we enter a function with arguments. It becomes more - // annoying when the scope has arguments, return_value and locals. - switch (kind) { - case eScopeKindLocals: - scope.presentationHint = protocol::Scope::eScopePresentationHintLocals; - scope.name = "Locals"; - break; - case eScopeKindGlobals: - scope.name = "Globals"; - break; - case eScopeKindRegisters: - scope.presentationHint = protocol::Scope::eScopePresentationHintRegisters; - scope.name = "Registers"; - break; +template StringMap distinct_names(T &container) { + StringMap variable_name_counts; + for (auto variable : container) { + if (!variable.IsValid()) + break; + variable_name_counts[GetNonNullVariableName(variable)]++; } - - return scope; + return variable_name_counts; } -std::vector -ScopeStore::GetVariables(VariableReferenceStorage &storage, - const Configuration &config, - const VariablesArguments &args) { - LoadVariables(); - if (m_kind == lldb_dap::eScopeKindRegisters) - SetRegistersFormat(); - - const bool format_hex = args.format ? args.format->hex : false; +template +std::vector make_variables( + VariableReferenceStorage &storage, const Configuration &config, + const VariablesArguments &args, T &container, bool is_permanent, + const std::map &name_overrides = {}) { std::vector variables; - if (m_kind == eScopeKindLocals) - AddReturnValue(storage, config, variables, format_hex); - - const uint64_t count = args.count; - const uint32_t start_idx = 0; - const uint32_t num_children = m_children.GetSize(); - const uint32_t end_idx = start_idx + ((count == 0) ? num_children : count); // We first find out which variable names are duplicated. - std::map variable_name_counts; - for (auto i = start_idx; i < end_idx; ++i) { - lldb::SBValue variable = m_children.GetValueAtIndex(i); - if (!variable.IsValid()) - break; - variable_name_counts[GetNonNullVariableName(variable)]++; - } + StringMap variable_name_counts = distinct_names(container); - // Now we construct the result with unique display variable names. - for (auto i = start_idx; i < end_idx; ++i) { - lldb::SBValue variable = m_children.GetValueAtIndex(i); + const bool format_hex = args.format ? args.format->hex : false; + auto start_it = begin(container) + args.start; + auto end_it = args.count == 0 ? end(container) : start_it + args.count; + // Now we construct the result with unique display variable names. + for (; start_it != end_it; start_it++) { + lldb::SBValue variable = *start_it; if (!variable.IsValid()) break; - const var_ref_t frame_var_ref = - storage.InsertVariable(variable, /*is_permanent=*/false); - if (LLVM_UNLIKELY(frame_var_ref.AsUInt32() >= + const var_ref_t var_ref = + HasInnerVarref(variable) + ? storage.Insert(variable, /*is_permanent=*/is_permanent) + : var_ref_t(var_ref_t::k_no_child); + if (LLVM_UNLIKELY(var_ref.AsUInt32() >= var_ref_t::k_variables_reference_threshold)) { DAP_LOG(storage.log, - "warning: scopes variablesReference threshold reached. " + "warning: variablesReference threshold reached. " "current: {} threshold: {}, maximum {}.", - frame_var_ref.AsUInt32(), - var_ref_t::k_variables_reference_threshold, + var_ref.AsUInt32(), var_ref_t::k_variables_reference_threshold, var_ref_t::k_max_variables_references); + break; } - if (LLVM_UNLIKELY(frame_var_ref.Kind() == eReferenceKindInvalid)) + if (LLVM_UNLIKELY(var_ref.Kind() == eReferenceKindInvalid)) break; + std::optional custom_name; + auto name_it = name_overrides.find(variable.GetID()); + if (name_it != name_overrides.end()) + custom_name = name_it->second; + variables.emplace_back(CreateVariable( - variable, frame_var_ref, format_hex, config.enableAutoVariableSummaries, + variable, var_ref, format_hex, config.enableAutoVariableSummaries, config.enableSyntheticChildDebugging, - variable_name_counts[GetNonNullVariableName(variable)] > 1)); + variable_name_counts[GetNonNullVariableName(variable)] > 1, + custom_name)); } + return variables; } -lldb::SBValue ScopeStore::FindVariable(llvm::StringRef name) { - LoadVariables(); - - lldb::SBValue variable; - const bool is_name_duplicated = name.contains(" @"); - // variablesReference is one of our scopes, not an actual variable it is - // asking for a variable in locals or globals or registers. - const uint32_t end_idx = m_children.GetSize(); - // Searching backward so that we choose the variable in closest scope - // among variables of the same name. - for (const uint32_t i : llvm::reverse(llvm::seq(0, end_idx))) { - lldb::SBValue curr_variable = m_children.GetValueAtIndex(i); - std::string variable_name = - CreateUniqueVariableNameForDisplay(curr_variable, is_name_duplicated); - if (variable_name == name) { - variable = curr_variable; - break; +/// A Variable store for fetching variables within a specific scope (locals, +/// globals, or registers) for a given stack frame. +class ScopeStore final : public VariableStore { +public: + explicit ScopeStore(ScopeKind kind, const lldb::SBFrame &frame) + : m_frame(frame), m_kind(kind) {} + + Expected> + GetVariables(VariableReferenceStorage &storage, const Configuration &config, + const VariablesArguments &args) override { + LoadVariables(); + if (m_error.Fail()) + return ToError(m_error); + return make_variables(storage, config, args, m_children, + /*is_permanent=*/false, m_names); + } + + lldb::SBValue FindVariable(llvm::StringRef name) override { + LoadVariables(); + + lldb::SBValue variable; + const bool is_name_duplicated = name.contains(" @"); + // variablesReference is one of our scopes, not an actual variable it is + // asking for a variable in locals or globals or registers. + const uint32_t end_idx = m_children.GetSize(); + // Searching backward so that we choose the variable in closest scope + // among variables of the same name. + for (const uint32_t i : reverse(seq(0, end_idx))) { + lldb::SBValue curr_variable = m_children.GetValueAtIndex(i); + std::string variable_name = + CreateUniqueVariableNameForDisplay(curr_variable, is_name_duplicated); + if (variable_name == name) { + variable = curr_variable; + break; + } } + return variable; } - return variable; -} -void ScopeStore::LoadVariables() { - if (m_variables_loaded) - return; + lldb::SBValue GetVariable() const override { return lldb::SBValue(); } - m_variables_loaded = true; - switch (m_kind) { - case eScopeKindLocals: - m_children = m_frame.GetVariables(/*arguments=*/true, - /*locals=*/true, - /*statics=*/false, - /*in_scope_only=*/true); - break; - case eScopeKindGlobals: - m_children = m_frame.GetVariables(/*arguments=*/false, - /*locals=*/false, - /*statics=*/true, - /*in_scope_only=*/true); - break; - case eScopeKindRegisters: - m_children = m_frame.GetRegisters(); - } -} +private: + void LoadVariables() { + if (m_variables_loaded) + return; -void ScopeStore::SetRegistersFormat() { - // Change the default format of any pointer sized registers in the first - // register set to be the lldb::eFormatAddressInfo so we show the pointer - // and resolve what the pointer resolves to. Only change the format if the - // format was set to the default format or if it was hex as some registers - // have formats set for them. - const uint32_t addr_size = - m_frame.GetThread().GetProcess().GetAddressByteSize(); - for (lldb::SBValue reg : m_children.GetValueAtIndex(0)) { - const lldb::Format format = reg.GetFormat(); - if (format == lldb::eFormatDefault || format == lldb::eFormatHex) { - if (reg.GetByteSize() == addr_size) - reg.SetFormat(lldb::eFormatAddressInfo); + m_variables_loaded = true; + + // TODO: Support "arguments" and "return value" scope. + // At the moment lldb-dap includes the arguments and return_value into the + // "locals" scope. + // VS Code only expands the first non-expensive scope. This causes friction + // if we add the arguments above the local scope, as the locals scope will + // not be expanded if we enter a function with arguments. It becomes more + // annoying when the scope has arguments, return_value and locals. + switch (m_kind) { + case eScopeKindLocals: { + // Show return value if there is any (in the local top frame) + lldb::SBValue stop_return_value; + if (m_frame.GetFrameID() == 0 && + ((stop_return_value = m_frame.GetThread().GetStopReturnValue()))) { + // FIXME: Cloning this value seems to change the type summary, see + // https://github.com/llvm/llvm-project/issues/183578 + // m_children.Append(stop_return_value.Clone("(Return Value)")); + m_names[stop_return_value.GetID()] = "(Return Value)"; + m_children.Append(stop_return_value); + } + lldb::SBValueList locals = m_frame.GetVariables(/*arguments=*/true, + /*locals=*/true, + /*statics=*/false, + /*in_scope_only=*/true); + m_children.Append(locals); + // Save the error since we cannot insert into the SBValueList + m_error = locals.GetError(); + } break; + case eScopeKindGlobals: + m_children = m_frame.GetVariables(/*arguments=*/false, + /*locals=*/false, + /*statics=*/true, + /*in_scope_only=*/true); + m_error = m_children.GetError(); + break; + case eScopeKindRegisters: + m_children = m_frame.GetRegisters(); + // Change the default format of any pointer sized registers in the first + // register set to be the lldb::eFormatAddressInfo so we show the pointer + // and resolve what the pointer resolves to. Only change the format if the + // format was set to the default format or if it was hex as some registers + // have formats set for them. + const uint32_t addr_size = + m_frame.GetThread().GetProcess().GetAddressByteSize(); + for (lldb::SBValue reg : m_children.GetValueAtIndex(0)) { + const lldb::Format format = reg.GetFormat(); + if (format == lldb::eFormatDefault || format == lldb::eFormatHex) { + if (reg.GetByteSize() == addr_size) + reg.SetFormat(lldb::eFormatAddressInfo); + } + } } } -} -void ScopeStore::AddReturnValue(VariableReferenceStorage &storage, - const Configuration &config, - std::vector &variables, - bool format_hex) { - assert(m_kind == eScopeKindLocals && - "Return Value Should only be in local scope"); - if (m_children.GetSize() == 0) { - // Check for an error in the SBValueList that might explain why we don't - // have locals. If we have an error display it as the sole value in the - // the locals. - - // "error" owns the error string so we must keep it alive as long as we - // want to use the returns "const char *". - lldb::SBError error = m_children.GetError(); - if (const char *var_err = error.GetCString()) { - // Create a fake variable named "error" to explain why variables were - // not available. This new error will help let users know when there was - // a problem that kept variables from being available for display and - // allow users to fix this issue instead of seeing no variables. The - // errors are only set when there is a problem that the user could - // fix, so no error will show up when you have no debug info, only when - // we do have debug info and something that is fixable can be done. - Variable err_var; - err_var.name = ""; - err_var.type = "const char *"; - err_var.value = var_err; - variables.push_back(std::move(err_var)); + lldb::SBFrame m_frame; + lldb::SBValueList m_children; + lldb::SBError m_error; + std::map m_names; + ScopeKind m_kind; + bool m_variables_loaded = false; +}; + +/// Variable store for expandable values. +/// +/// Manages children variables of complex types (structs, arrays, pointers, +/// etc.) that can be expanded in the debugger UI. +class ExpandableValueStore final : public VariableStore { + +public: + explicit ExpandableValueStore(const lldb::SBValue &value) : m_value(value) {} + + llvm::Expected> + GetVariables(VariableReferenceStorage &storage, + const protocol::Configuration &config, + const protocol::VariablesArguments &args) override { + std::map name_overrides; + lldb::SBValueList list; + for (auto inner : m_value) + list.Append(inner); + + // We insert a new "[raw]" child that can be used to inspect the raw version + // of a synthetic member. That eliminates the need for the user to go to the + // debug console and type `frame var to get these values. + if (config.enableSyntheticChildDebugging && m_value.IsSynthetic()) { + lldb::SBValue synthetic_value = m_value.GetSyntheticValue(); + name_overrides[synthetic_value.GetID()] = "[raw]"; + // FIXME: Cloning the value seems to affect the type summary, see + // https://github.com/llvm/llvm-project/issues/183578 + // m_value.GetSyntheticValue().Clone("[raw]"); + list.Append(synthetic_value); } - return; + + const bool is_permanent = + args.variablesReference.Kind() == eReferenceKindPermanent; + return make_variables(storage, config, args, list, is_permanent, + name_overrides); } - // Show return value if there is any ( in the local top frame ) - lldb::SBThread selected_thread = m_frame.GetThread(); - lldb::SBValue stop_return_value = selected_thread.GetStopReturnValue(); + lldb::SBValue FindVariable(llvm::StringRef name) override { + if (name == "[raw]" && m_value.IsSynthetic()) + return m_value.GetSyntheticValue(); - if (stop_return_value.IsValid() && - (selected_thread.GetSelectedFrame().GetFrameID() == 0)) { - auto renamed_return_value = stop_return_value.Clone("(Return Value)"); - var_ref_t return_var_ref{var_ref_t::k_no_child}; + // Handle mapped index + lldb::SBValue variable = m_value.GetChildMemberWithName(name.data()); + if (variable.IsValid()) + return variable; - if (stop_return_value.MightHaveChildren() || - stop_return_value.IsSynthetic()) { - return_var_ref = storage.InsertVariable(stop_return_value, - /*is_permanent=*/false); - } - variables.emplace_back( - CreateVariable(renamed_return_value, return_var_ref, format_hex, - config.enableAutoVariableSummaries, - config.enableSyntheticChildDebugging, false)); + // Handle array indexes + uint64_t index = 0; + if (name.consume_front('[') && name.consume_back("]") && + !name.consumeInteger(0, index)) + variable = m_value.GetChildAtIndex(index); + + return variable; } -} -std::vector -ExpandableValueStore::GetVariables(VariableReferenceStorage &storage, - const Configuration &config, - const VariablesArguments &args) { - const var_ref_t var_ref = args.variablesReference; - const uint64_t count = args.count; - const uint64_t start = args.start; - const bool hex = args.format ? args.format->hex : false; - - lldb::SBValue variable = storage.GetVariable(var_ref); - if (!variable) - return {}; - - // We are expanding a variable that has children, so we will return its - // children. - std::vector variables; - const bool is_permanent = var_ref.Kind() == eReferenceKindPermanent; - auto addChild = [&](lldb::SBValue child, - std::optional custom_name = {}) { - if (!child.IsValid()) - return; + [[nodiscard]] lldb::SBValue GetVariable() const override { return m_value; } - const var_ref_t child_var_ref = storage.InsertVariable(child, is_permanent); - if (LLVM_UNLIKELY(child_var_ref.AsUInt32() == - var_ref_t::k_variables_reference_threshold)) { - DAP_LOG(storage.log, - "warning: {} variablesReference threshold reached. " - "current: {} threshold: {}, maximum {}.", - (is_permanent ? "permanent" : "temporary"), - child_var_ref.AsUInt32(), - var_ref_t::k_variables_reference_threshold, - var_ref_t::k_max_variables_references); - } +private: + lldb::SBValue m_value; +}; - if (LLVM_UNLIKELY(child_var_ref.Kind() == eReferenceKindInvalid)) { - DAP_LOG(storage.log, - "error: invalid variablesReference created for {} variable {}.", - (is_permanent ? "permanent" : "temporary"), variable.GetName()); - return; - } +class ExpandableValueListStore final : public VariableStore { - variables.emplace_back(CreateVariable( - child, child_var_ref, hex, config.enableAutoVariableSummaries, - config.enableSyntheticChildDebugging, - /*is_name_duplicated=*/false, custom_name)); - }; +public: + explicit ExpandableValueListStore(const lldb::SBValueList &list) + : m_value_list(list) {} - const uint32_t num_children = variable.GetNumChildren(); - const uint32_t end_idx = start + ((count == 0) ? num_children : count); - uint32_t i = start; - for (; i < end_idx && i < num_children; ++i) - addChild(variable.GetChildAtIndex(i)); + llvm::Expected> + GetVariables(VariableReferenceStorage &storage, + const protocol::Configuration &config, + const protocol::VariablesArguments &args) override { + return make_variables(storage, config, args, m_value_list, + /*is_permanent=*/true); + } - // If we haven't filled the count quota from the request, we insert a new - // "[raw]" child that can be used to inspect the raw version of a - // synthetic member. That eliminates the need for the user to go to the - // debug console and type `frame var to get these values. - if (config.enableSyntheticChildDebugging && variable.IsSynthetic() && - i == num_children) - addChild(variable.GetNonSyntheticValue(), "[raw]"); + lldb::SBValue FindVariable(llvm::StringRef name) override { + lldb::SBValue variable = m_value_list.GetFirstValueByName(name.data()); + if (variable.IsValid()) + return variable; - return variables; -} + return lldb::SBValue(); + } -lldb::SBValue ExpandableValueStore::FindVariable(llvm::StringRef name) { - lldb::SBValue variable = m_value.GetChildMemberWithName(name.data()); - if (variable.IsValid()) - return variable; + [[nodiscard]] lldb::SBValue GetVariable() const override { + return lldb::SBValue(); + } - if (name.consume_front('[') && name.consume_back("]")) { - uint64_t index = 0; - if (!name.consumeInteger(0, index)) { - variable = m_value.GetChildAtIndex(index); - } +private: + lldb::SBValueList m_value_list; +}; + +} // namespace + +namespace lldb_dap { + +protocol::Scope CreateScope(ScopeKind kind, var_ref_t variablesReference, + bool expensive) { + protocol::Scope scope; + scope.variablesReference = variablesReference; + scope.expensive = expensive; + + switch (kind) { + case eScopeKindLocals: + scope.presentationHint = protocol::Scope::eScopePresentationHintLocals; + scope.name = "Locals"; + break; + case eScopeKindGlobals: + scope.name = "Globals"; + break; + case eScopeKindRegisters: + scope.presentationHint = protocol::Scope::eScopePresentationHintRegisters; + scope.name = "Registers"; + break; } - return variable; + + return scope; } lldb::SBValue VariableReferenceStorage::GetVariable(var_ref_t var_ref) { @@ -324,27 +342,23 @@ lldb::SBValue VariableReferenceStorage::GetVariable(var_ref_t var_ref) { return {}; } -var_ref_t -VariableReferenceStorage::InsertVariable(const lldb::SBValue &variable, - bool is_permanent) { +var_ref_t VariableReferenceStorage::Insert(const lldb::SBValue &variable, + bool is_permanent) { if (is_permanent) - return m_permanent_kind_pool.Add(variable); + return m_permanent_kind_pool.Add(variable); - return m_temporary_kind_pool.Add(variable); + return m_temporary_kind_pool.Add(variable); } -lldb::SBValue VariableReferenceStorage::FindVariable(var_ref_t var_ref, - llvm::StringRef name) { - if (VariableStore *store = GetVariableStore(var_ref)) - return store->FindVariable(name); - - return {}; +var_ref_t VariableReferenceStorage::Insert(const lldb::SBValueList &values) { + return m_permanent_kind_pool.Add(values); } std::vector -VariableReferenceStorage::CreateScopes(lldb::SBFrame &frame) { +VariableReferenceStorage::Insert(const lldb::SBFrame &frame) { auto create_scope = [&](ScopeKind kind) { - const var_ref_t var_ref = m_scope_kind_pool.Add(kind, frame); + const var_ref_t var_ref = + m_temporary_kind_pool.Add(kind, frame); const bool is_expensive = kind != eScopeKindLocals; return CreateScope(kind, var_ref, is_expensive); }; @@ -353,6 +367,14 @@ VariableReferenceStorage::CreateScopes(lldb::SBFrame &frame) { create_scope(eScopeKindRegisters)}; } +lldb::SBValue VariableReferenceStorage::FindVariable(var_ref_t var_ref, + llvm::StringRef name) { + if (VariableStore *store = GetVariableStore(var_ref)) + return store->FindVariable(name); + + return {}; +} + VariableStore *VariableReferenceStorage::GetVariableStore(var_ref_t var_ref) { const ReferenceKind kind = var_ref.Kind(); switch (kind) { @@ -360,9 +382,7 @@ VariableStore *VariableReferenceStorage::GetVariableStore(var_ref_t var_ref) { return m_permanent_kind_pool.GetVariableStore(var_ref); case eReferenceKindTemporary: return m_temporary_kind_pool.GetVariableStore(var_ref); - case eReferenceKindScope: - return m_scope_kind_pool.GetVariableStore(var_ref); - default: + case eReferenceKindInvalid: return nullptr; } llvm_unreachable("Unknown reference kind."); diff --git a/lldb/tools/lldb-dap/Variables.h b/lldb/tools/lldb-dap/Variables.h index 109e6f9077346..bc6c4637fac80 100644 --- a/lldb/tools/lldb-dap/Variables.h +++ b/lldb/tools/lldb-dap/Variables.h @@ -50,11 +50,12 @@ class VariableStore { explicit VariableStore() = default; virtual ~VariableStore() = default; - virtual std::vector + virtual llvm::Expected> GetVariables(VariableReferenceStorage &storage, const protocol::Configuration &config, const protocol::VariablesArguments &args) = 0; virtual lldb::SBValue FindVariable(llvm::StringRef name) = 0; + virtual lldb::SBValue GetVariable() const = 0; // Not copyable. VariableStore(const VariableStore &) = delete; @@ -63,52 +64,6 @@ class VariableStore { VariableStore &operator=(VariableStore &&) = default; }; -/// A Variable store for fetching variables within a specific scope (locals, -/// globals, or registers) for a given stack frame. -class ScopeStore final : public VariableStore { -public: - explicit ScopeStore(ScopeKind kind, const lldb::SBFrame &frame) - : m_frame(frame), m_kind(kind) {} - - std::vector - GetVariables(VariableReferenceStorage &storage, - const protocol::Configuration &config, - const protocol::VariablesArguments &args) override; - lldb::SBValue FindVariable(llvm::StringRef name) override; - -private: - void LoadVariables(); - void SetRegistersFormat(); - void AddReturnValue(VariableReferenceStorage &storage, - const protocol::Configuration &config, - std::vector &variables, - bool format_hex); - lldb::SBFrame m_frame; - lldb::SBValueList m_children; - ScopeKind m_kind; - bool m_variables_loaded = false; -}; - -/// Variable store for expandable values. -/// -/// Manages children variables of complex types (structs, arrays, pointers, -/// etc.) that can be expanded in the debugger UI. -class ExpandableValueStore final : public VariableStore { - -public: - explicit ExpandableValueStore(const lldb::SBValue &value) : m_value(value) {} - - std::vector - GetVariables(VariableReferenceStorage &storage, - const protocol::Configuration &config, - const protocol::VariablesArguments &args) override; - lldb::SBValue FindVariable(llvm::StringRef name) override; - [[nodiscard]] lldb::SBValue GetVariable() const { return m_value; }; - -private: - lldb::SBValue m_value; -}; - struct VariableReferenceStorage { explicit VariableReferenceStorage(Log &log) : log(log) {} /// \return a new variableReference. @@ -123,16 +78,18 @@ struct VariableReferenceStorage { /// Insert a new \p variable. /// \return variableReference assigned to this expandable variable. - var_ref_t InsertVariable(const lldb::SBValue &variable, bool is_permanent); + var_ref_t Insert(const lldb::SBValue &variable, bool is_permanent); - lldb::SBValue FindVariable(var_ref_t var_ref, llvm::StringRef name); + /// Insert a value list. Used to store references to lldb repl command + /// outputs. + var_ref_t Insert(const lldb::SBValueList &values); - std::vector CreateScopes(lldb::SBFrame &frame); + /// Insert a new frame into temporary storage. + std::vector Insert(const lldb::SBFrame &frame); - void Clear() { - m_temporary_kind_pool.Clear(); - m_scope_kind_pool.Clear(); - } + lldb::SBValue FindVariable(var_ref_t var_ref, llvm::StringRef name); + + void Clear() { m_temporary_kind_pool.Clear(); } VariableStore *GetVariableStore(var_ref_t var_ref); Log &log; @@ -142,13 +99,9 @@ struct VariableReferenceStorage { /// All references created starts from zero with the Reference kind mask /// applied, the mask is then removed when fetching a variable store /// - /// \tparam VariableStoreType - /// The type of variable store to use. - /// /// \tparam ReferenceKind /// The reference kind created in this pool - template - class ReferenceKindPool { + template class ReferenceKindPool { public: explicit ReferenceKindPool() = default; @@ -162,15 +115,15 @@ struct VariableReferenceStorage { m_pool.clear(); } - VariableStoreType *GetVariableStore(var_ref_t var_ref) { + VariableStore *GetVariableStore(var_ref_t var_ref) { const uint32_t raw_ref = var_ref.Reference(); if (raw_ref != 0 && raw_ref <= m_pool.size()) - return &m_pool[raw_ref - 1]; + return m_pool[raw_ref - 1].get(); return nullptr; } - template var_ref_t Add(Args &&...args) { + template var_ref_t Add(Args &&...args) { assert(reference_count == m_pool.size() && "Current reference_count must be the size of the pool"); @@ -180,7 +133,7 @@ struct VariableReferenceStorage { return var_ref_t(var_ref_t::k_invalid_var_ref); } - m_pool.emplace_back(std::forward(args)...); + m_pool.emplace_back(std::make_unique(std::forward(args)...)); const uint32_t raw_ref = NextRawReference(); return var_ref_t(raw_ref, Kind); } @@ -201,19 +154,15 @@ struct VariableReferenceStorage { } uint32_t reference_count = 0; - std::vector m_pool; + std::vector> m_pool; }; /// Variables that are alive in this stop state. /// Will be cleared when debuggee resumes. - ReferenceKindPool - m_temporary_kind_pool; + ReferenceKindPool m_temporary_kind_pool; /// Variables that persist across entire debug session. /// These are the variables evaluated from debug console REPL. - ReferenceKindPool - m_permanent_kind_pool; - ReferenceKindPool - m_scope_kind_pool; + ReferenceKindPool m_permanent_kind_pool; }; } // namespace lldb_dap diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index 0e6cd26abe2eb..81ebd3f51fa94 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -61,22 +61,16 @@ TEST(DAPTypesTest, DAPSymbol) { TEST(DapTypesTest, DAP_var_ref_t) { // Check the masked ref constructor. - const uint32_t scope_masked_var_ref = 0x2000001; - const var_ref_t scope_ref(scope_masked_var_ref); - EXPECT_EQ(scope_ref.AsUInt32(), scope_masked_var_ref); - EXPECT_EQ(scope_ref.Reference(), 1U); - EXPECT_EQ(scope_ref.Kind(), eReferenceKindScope); - - const uint32_t temp_masked_var_ref = 0x0000021; + const uint32_t temp_masked_var_ref = 0x00000201U; const var_ref_t temp_ref(temp_masked_var_ref); EXPECT_EQ(temp_ref.AsUInt32(), temp_masked_var_ref); - EXPECT_EQ(temp_ref.Reference(), 0x21U); + EXPECT_EQ(temp_ref.Reference(), 0x0201U); EXPECT_EQ(temp_ref.Kind(), eReferenceKindTemporary); - const uint32_t perm_masked_var_ref = 0x1000032; + const uint32_t perm_masked_var_ref = 0x1000032U; const var_ref_t perm_ref(perm_masked_var_ref); EXPECT_EQ(perm_ref.AsUInt32(), perm_masked_var_ref); - EXPECT_EQ(perm_ref.Reference(), 0x32U); + EXPECT_EQ(perm_ref.Reference(), 0x032U); EXPECT_EQ(perm_ref.Kind(), eReferenceKindPermanent); const var_ref_t invalid_ref{}; @@ -96,11 +90,11 @@ TEST(DapTypesTest, DAP_var_ref_t) { EXPECT_EQ(no_child_ref.Kind(), eReferenceKindTemporary); // Check the refkind constructor. - const uint32_t scope2_masked_ref = 0x2000003; - const var_ref_t scope_ref2(3, eReferenceKindScope); + const uint32_t scope2_masked_ref = 0x0000003; + const var_ref_t scope_ref2(3, eReferenceKindTemporary); EXPECT_EQ(scope_ref2.AsUInt32(), scope2_masked_ref); EXPECT_EQ(scope_ref2.Reference(), 3U); - EXPECT_EQ(scope_ref2.Kind(), eReferenceKindScope); + EXPECT_EQ(scope_ref2.Kind(), eReferenceKindTemporary); EXPECT_EQ(var_ref_t().AsUInt32(), var_ref_t{var_ref_t::k_invalid_var_ref}.AsUInt32()); diff --git a/lldb/unittests/DAP/Inputs/linux-x86_64.core.yaml b/lldb/unittests/DAP/Inputs/linux-x86_64.core.yaml index 392418f7e82de..30ec3b9c0a7df 100644 --- a/lldb/unittests/DAP/Inputs/linux-x86_64.core.yaml +++ b/lldb/unittests/DAP/Inputs/linux-x86_64.core.yaml @@ -1,49 +1,850 @@ +# Built using: +# clang -g sample.c # from linux-x86_64.out.yaml +# lldb a.out -b -o 'break set -l 6 -C "process save-core -s stack -pminidump a.out.core"' -o 'r' --- !minidump Streams: + - Type: LLDBGenerated + Content: '' - Type: SystemInfo Processor Arch: AMD64 Platform ID: Linux + CPU: + Vendor ID: "\0\0\0\0\0\0\0\0\0\0\0\0" + Version Info: 0x0 + Feature Info: 0x0 - Type: ModuleList Modules: - - Base of Image: 0x400000 - Size of Image: 0x1E0 - Time Date Stamp: 1747851624 - Module Name: 'linux-x86_64.out' - CodeView Record: 4C45704201DF54A6045E657D3F8FFB9CE111878914F8BD6D - Reserved0: 0xFFFFFFF800000001 - Reserved1: 0x2AE15B07FFFFFFF - - Base of Image: 0x7FFC24129000 - Size of Image: 0xA0C - Time Date Stamp: 1747851624 - Module Name: '[vdso](0x00007ffc24129000)' - CodeView Record: 4C4570428CBE1E6C351152C0C43E68C4EF417DB4C77E8EBD - Reserved0: 0xFFFFFFF800000001 - Reserved1: 0x2AE15B07FFFFFFF + - Base of Image: 0x555555554000 + Size of Image: 0x628 + Time Date Stamp: 1771959187 + Module Name: '/tmp/a.out' + CodeView Record: 4C457042768D260BD4FC15E892AAC361C910DF78AC15E194 + - Base of Image: 0x7FFFF7FC7000 + Size of Image: 0xCC8 + Time Date Stamp: 1771959187 + Module Name: '/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2' + CodeView Record: 4C45704208CCCC2A9388D5247CCB3E864F3063B975B0A15D + - Base of Image: 0x7FFFF7FC5000 + Size of Image: 0x1817 + Time Date Stamp: 1771959187 + Module Name: '[vdso](0x00007ffff7fc5000)' + CodeView Record: 4C4570429312E1299072A115C3ACA82B8640192845D0A551 + - Base of Image: 0x7FFFF7DB1000 + Size of Image: 0x274E8 + Time Date Stamp: 1771959187 + Module Name: '/lib/x86_64-linux-gnu/libc.so.6' + CodeView Record: 4C45704261E1DEA1F540B3B4B4D8EC76716E409CEC096ECE - Type: MiscInfo - Content: 1800000001000000037E000000000000509F306F01000000 + Content: 1800000001000000A72D3700000000000000000000000000 - Type: ThreadList Threads: - - Thread Id: 0x7E03 - Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700100000000000FFFFFFFF0000FFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E8150B24FC7F0000E8150B24FC7F00000C014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - Thread Id: 0x372DA7 + Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700108000000000330000000000000000002B00020200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E40D87D55555555000008D6FFFFFF7F0000F8D5FFFFFF7F0000A0D4FFFFFF7F0000A0D4FFFFFF7F0000F8D5FFFFFF7F0000B0D4FFFFFF7F0000000000000000000080BCFCF7FF7F000020D2FFFFFF7F00000202000000000000000000000000000008D6FFFFFF7F000000D0FFF7FF7F0000D87D5555555500004851555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040E7DAF7FF7F00000000000000000000 Stack: - Start of Memory Range: 0x7FFC240B1568 - Content: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006218160B24FC7F000042014000000000000C0140000000000000000000000000000000000000000000000000000000006638160B24FC7F00005F014000000000000000000000000000000000000000005F0000000000000000010000000000000002200B24FC7F00000000000000000000FE2F0B24FC7F00000000000000000000210000000000000000901224FC7F00001000000000000000FFFBEBBF0000000006000000000000000010000000000000110000000000000064000000000000000300000000000000400040000000000004000000000000003800000000000000050000000000000003000000000000000700000000000000000000000000000008000000000000000000000000000000090000000000000044014000000000000B0000000000000000000000000000000C0000000000000000000000000000000D0000000000000000000000000000000E000000000000000000000000000000170000000000000000000000000000001900000000000000A9170B24FC7F00001A0000000000000000000000000000001F00000000000000FC3F0B24FC7F00000F00000000000000B9170B24FC7F000000000000000000000000000000000000000AB340B9514A4C453C3FB52168ADE70E7838365F36340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574005F3D2F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574002F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574000000000000000000 + Start of Memory Range: 0x7FFFFFFFD420 + Content: 0000C000000000000000C0000000000000010000000000000000C0000000000040000000000000001000000000000000000008000000000029018C2100000000170000000000000000000000000000000000000000000000000000000000000017000000310000000000000000000000B0D4FFFFFF7F00000000000000000000E0D4FFFFFF7F0000CB515555555500000000000000001440000000000000144000000000000039400000000000003E40F8D5FFFFFF7F000001000000000000000100000000000000A8ACDDF7FF7F0000E0D5FFFFFF7F000080515555555500004040555501000000F8D5FFFFFF7F0000F8D5FFFFFF7F00005002D40952A1CA98000000000000000008D6FFFFFF7F000000D0FFF7FF7F0000D87D555555550000500236A0AD5E356750021651E94E3567000000000000000000000000000000000000000000000000F8D5FFFFFF7F00000100000000000000007B97470D7B2415F0D5FFFFFF7F000065ADDDF7FF7F00008051555555550000D87D55555555000010E3FFF7FF7F0000000000000000000000000000000000005050555555550000F0D5FFFFFF7F0000000000000000000000000000000000007150555555550000E8D5FFFFFF7F00003800000000000000010000000000000079D9FFFFFF7F0000000000000000000084D9FFFFFF7F0000B3D9FFFFFF7F0000D3D9FFFFFF7F000002DAFFFFFF7F000010DAFFFFFF7F000030DAFFFFFF7F00003FDAFFFFFF7F0000BCE1FFFFFF7F0000DAE1FFFFFF7F000000E2FFFFFF7F000010E2FFFFFF7F000048E2FFFFFF7F000055E2FFFFFF7F000078E2FFFFFF7F00008BE2FFFFFF7F00009EE2FFFFFF7F0000CFE2FFFFFF7F0000FEE2FFFFFF7F00003CE3FFFFFF7F00006DE3FFFFFF7F00007DE3FFFFFF7F0000B9E3FFFFFF7F0000ECE3FFFFFF7F000003E4FFFFFF7F000083E4FFFFFF7F000098E4FFFFFF7F0000BBE4FFFFFF7F0000F2E4FFFFFF7F000086EAFFFFFF7F00008EEAFFFFFF7F0000C1EAFFFFFF7F0000E3EAFFFFFF7F000014EBFFFFFF7F000071EBFFFFFF7F000085EBFFFFFF7F0000BAEBFFFFFF7F0000CAEBFFFFFF7F0000E6EBFFFFFF7F00003EECFFFFFF7F00009CECFFFFFF7F0000B1ECFFFFFF7F0000E2ECFFFFFF7F000019EDFFFFFF7F000048EDFFFFFF7F000079EDFFFFFF7F00008AEDFFFFFF7F0000B4EDFFFFFF7F0000E9EDFFFFFF7F00000AEEFFFFFF7F000037EEFFFFFF7F00006CEEFFFFFF7F0000AEEEFFFFFF7F0000BAEEFFFFFF7F0000F1EEFFFFFF7F000008EFFFFFFF7F000033EFFFFFFF7F000062EFFFFFFF7F00008CEFFFFFFF7F0000B0EFFFFFFF7F0000000000000000000021000000000000000050FCF7FF7F00003300000000000000F0060000000000001000000000000000FFFB8B17000000000600000000000000001000000000000011000000000000006400000000000000030000000000000040405555555500000400000000000000380000000000000005000000000000000E0000000000000007000000000000000070FCF7FF7F000008000000000000000000000000000000090000000000000050505555555500000B0000000000000014A00700000000000C0000000000000014A00700000000000D00000000000000535F0100000000000E00000000000000535F01000000000017000000000000000000000000000000190000000000000059D9FFFFFF7F00001A0000000000000002000000000000001F00000000000000EDEFFFFFFF7F00000F0000000000000069D9FFFFFF7F00001B000000000000001C000000000000001C0000000000000020000000000000000000000000000000000000000000000000C27B97470D7B2415EB04A950654C28017838365F3634000000000000000000002F746D702F612E6F757400434C4F554453444B5F434F4E544558545F41574152455F5553455F4543505F485454505F50524F58593D74727565004C4553534F50454E3D7C202F7573722F62696E2F6C6573737069706520257300424153485F46554E435F6E706D25253D2829207B20202F7573722F62696E2F67706B67206E706D20222440220A7D005253594E435F5253483D73736800504152494E49543D72546267715220423D2E3F5F415F6120513D5F733E7C3A004D4F54445F53484F574E3D70616D004C535F434F4C4F52533D72733D303A64693D30313B33343A6C6E3D30313B33363A6D683D30303A70693D34303B33333A736F3D30313B33353A646F3D30313B33353A62643D34303B33333B30313A63643D34303B33333B30313A6F723D34303B33313B30313A6D693D30303A73753D33373B34313A73673D33303B34333A63613D30303A74773D33303B34323A6F773D33343B34323A73743D33373B34343A65783D30313B33323A2A2E377A3D30313B33313A2A2E6163653D30313B33313A2A2E616C7A3D30313B33313A2A2E61706B3D30313B33313A2A2E6172633D30313B33313A2A2E61726A3D30313B33313A2A2E627A3D30313B33313A2A2E627A323D30313B33313A2A2E6361623D30313B33313A2A2E6370696F3D30313B33313A2A2E63726174653D30313B33313A2A2E6465623D30313B33313A2A2E6472706D3D30313B33313A2A2E64776D3D30313B33313A2A2E647A3D30313B33313A2A2E6561723D30313B33313A2A2E6567673D30313B33313A2A2E6573643D30313B33313A2A2E677A3D30313B33313A2A2E6A61723D30313B33313A2A2E6C68613D30313B33313A2A2E6C727A3D30313B33313A2A2E6C7A3D30313B33313A2A2E6C7A343D30313B33313A2A2E6C7A683D30313B33313A2A2E6C7A6D613D30313B33313A2A2E6C7A6F3D30313B33313A2A2E70797A3D30313B33313A2A2E7261723D30313B33313A2A2E72706D3D30313B33313A2A2E727A3D30313B33313A2A2E7361723D30313B33313A2A2E73776D3D30313B33313A2A2E74377A3D30313B33313A2A2E7461723D30313B33313A2A2E74617A3D30313B33313A2A2E74627A3D30313B33313A2A2E74627A323D30313B33313A2A2E74677A3D30313B33313A2A2E746C7A3D30313B33313A2A2E74787A3D30313B33313A2A2E747A3D30313B33313A2A2E747A6F3D30313B33313A2A2E747A73743D30313B33313A2A2E756465623D30313B33313A2A2E7761723D30313B33313A2A2E77686C3D30313B33313A2A2E77696D3D30313B33313A2A2E787A3D30313B33313A2A2E7A3D30313B33313A2A2E7A69703D30313B33313A2A2E7A6F6F3D30313B33313A2A2E7A73743D30313B33313A2A2E617669663D30313B33353A2A2E6A70673D30313B33353A2A2E6A7065673D30313B33353A2A2E6A786C3D30313B33353A2A2E6D6A70673D30313B33353A2A2E6D6A7065673D30313B33353A2A2E6769663D30313B33353A2A2E626D703D30313B33353A2A2E70626D3D30313B33353A2A2E70676D3D30313B33353A2A2E70706D3D30313B33353A2A2E7467613D30313B33353A2A2E78626D3D30313B33353A2A2E78706D3D30313B33353A2A2E7469663D30313B33353A2A2E746966663D30313B33353A2A2E706E673D30313B33353A2A2E7376673D30313B33353A2A2E7376677A3D30313B33353A2A2E6D6E673D30313B33353A2A2E7063783D30313B33353A2A2E6D6F763D30313B33353A2A2E6D70673D30313B33353A2A2E6D7065673D30313B33353A2A2E6D32763D30313B33353A2A2E6D6B763D30313B33353A2A2E7765626D3D30313B33353A2A2E776562703D30313B33353A2A2E6F676D3D30313B33353A2A2E6D70343D30313B33353A2A2E6D34763D30313B33353A2A2E6D7034763D30313B33353A2A2E766F623D30313B33353A2A2E71743D30313B33353A2A2E6E75763D30313B33353A2A2E776D763D30313B33353A2A2E6173663D30313B33353A2A2E726D3D30313B33353A2A2E726D76623D30313B33353A2A2E666C633D30313B33353A2A2E6176693D30313B33353A2A2E666C693D30313B33353A2A2E666C763D30313B33353A2A2E676C3D30313B33353A2A2E646C3D30313B33353A2A2E7863663D30313B33353A2A2E7877643D30313B33353A2A2E7975763D30313B33353A2A2E63676D3D30313B33353A2A2E656D663D30313B33353A2A2E6F67763D30313B33353A2A2E6F67783D30313B33353A2A2E6161633D30303B33363A2A2E61753D30303B33363A2A2E666C61633D30303B33363A2A2E6D34613D30303B33363A2A2E6D69643D30303B33363A2A2E6D6964693D30303B33363A2A2E6D6B613D30303B33363A2A2E6D70333D30303B33363A2A2E6D70633D30303B33363A2A2E6F67673D30303B33363A2A2E72613D30303B33363A2A2E7761763D30303B33363A2A2E6F67613D30303B33363A2A2E6F7075733D30303B33363A2A2E7370783D30303B33363A2A2E787370663D30303B33363A2A7E3D30303B39303A2A233D30303B39303A2A2E62616B3D30303B39303A2A2E6372646F776E6C6F61643D30303B39303A2A2E64706B672D646973743D30303B39303A2A2E64706B672D6E65773D30303B39303A2A2E64706B672D6F6C643D30303B39303A2A2E64706B672D746D703D30303B39303A2A2E6F6C643D30303B39303A2A2E6F7269673D30303B39303A2A2E706172743D30303B39303A2A2E72656A3D30303B39303A2A2E72706D6E65773D30303B39303A2A2E72706D6F7269673D30303B39303A2A2E72706D736176653D30303B39303A2A2E7377703D30303B39303A2A2E746D703D30303B39303A2A2E7563662D646973743D30303B39303A2A2E7563662D6E65773D30303B39303A2A2E7563662D6F6C643D30303B39303A00534B5F5349474E494E475F504C5547494E3D676E756262796167656E7400474F4F474C455F434C4F55445F44495341424C455F4449524543545F504154483D74727565005F3D2F7573722F62696E2F6C6C646200444255535F53455353494F4E5F4255535F414444524553533D756E69783A706174683D2F72756E2F757365722F3439393733322F62757300555345523D6861726A6F686E005353485F434C49454E543D3137322E3235332E33312E323337203437383431203232005034434F4E4649473D2E7034636F6E666967005353485F5454593D2F6465762F7074732F3000424153485F46554E435F7961726E25253D2829207B20202F7573722F62696E2F67706B67207961726E20222440220A7D00424153485F46554E435F6E707825253D2829207B20202F7573722F62696E2F67706B67206E707820222440220A7D0050344D455247453D2F676F6F676C652F7372632F66696C65732F686561642F6465706F742F656E672F706572666F7263652F6D6572676570342E74636C00424153485F46554E435F706E706D25253D2829207B20202F7573722F62696E2F67706B6720706E706D20222440220A7D004C4F474E414D453D6861726A6F686E00434C4F554453444B5F434F4E5441494E45525F5553455F4150504C49434154494F4E5F44454641554C545F43524544454E5449414C533D7472756500424153485F46554E435F686174636825253D2829207B20202F7573722F62696E2F67706B6720686174636820222440220A7D0048495354434F4E54524F4C3D69676E6F72656475707300504154483D2F7573722F6C69622F676F6F676C652D676F6C616E672F62696E3A2F7573722F6C6F63616C2F6275696C64746F6F6C732F6A6176612F6A646B2F62696E3A2F7573722F6C6F63616C2F7362696E3A2F7573722F6C6F63616C2F62696E3A2F7573722F7362696E3A2F7573722F62696E3A2F7362696E3A2F62696E005844475F53455353494F4E5F49443D6339303334005057443D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E00424153485F46554E435F7961726E706B6725253D2829207B20202F7573722F62696E2F67706B67207961726E706B6720222440220A7D005353485F415554485F4B45593D65636473612D736861322D6E697374703235362D636572742D763031406F70656E7373682E636F6D20414141414B47566A5A484E684C584E6F59544974626D6C7A644841794E54597459325679644331324D4446416233426C626E4E7A6143356A623230414141416747477568656C4D7545582B357530682B61516D78456E366B6A50433075574E47494C2B793543766B314F6F4141414149626D6C7A644841794E545941414142424250415938413859644E6A6770617A733930786C70703835623231517841416D6C446A384432444A386976546B7648434B676748742F6759495A32306B6A70665A7142644F6C7437385A6C5674725A42453872344D2B385A4141414145414A7A38774141414145414141415861474679616D396F626B426A62334A774C6D6476623264735A53356A62323041414141644141414142326868636D7076614734414141414F5A3239765A32786C58476868636D70766147344141414141615A335A42514141414142706E764E784141414141414141414D77414141415959325679644331745A5852685A4746305955426E6232396E6247557559323974414141414B67414141435949415249677755464C345761352B4368396B4D7047676F4A764F4F4C5747456E75417759724C5073445A4265427576496742674141414256775A584A7461585174574445784C575A76636E6468636D5270626D634141414141414141414633426C636D3170644331685A3256756443316D62334A3359584A6B6157356E414141414141414141425A775A584A7461585174634739796443316D62334A3359584A6B6157356E4141414141414141414170775A584A7461585174634852354141414141414141414135775A584A746158517464584E6C6369317959774141414141414141414141414142467741414141647A63326774636E4E6841414141417745414151414141514541764E305A533562314F5A59746F4A3150534B59344749776A69733169347A5A5A324D42644E2F544559714A494F56736641746B447268433959475356757961692F6B4F58774C4C6E4663356456445257484C4453427A6F5845676C34514B436D4E75396E6E65562F634D4C4571346430336F3144504F535051474A44712B776570344B3948755277767A6F673677544441354B70306C6F436E5759384D4854627434532F4F32526F356D76463078306563397663637757314B4F74632F4379645169476D6576425A4F514F795874385A435A4B4574534F5449506841453535574B386167744D45734A6C485274637377536732424A4E4A4D5365554B674C31416E2F6F434539624B414D452F7A585659564B354675763465707163636E6433735157325438716E694F4963454449346F796244656A6D3647385650772F707869655350626146476674754C79522F72485335324F68774141415251414141414D636E4E684C584E6F595449744D6A55324141414241477A374C6357654478443770523942723178684E624A73317345744B4D7257736C65775657692F56356A34647A3268484C64384B6C57753467746367356A767370793876594E58454950576C47683037745953695744575869444D575562765544314E514F794E345548686B595576574F2B647A372B4C71776C7A574D515A38796958775234714E4A666B343070666F65424B59384E71726E776A4B52724173446E53656E4B544B4E6F646A73666E684B5A4839784C566663456F544764674831364375625947396C31666D65613750724D37714F7250554F6E6B4B565548736F6475766A6F72475A335063476258536176646E7A467836446A6251726D514462523638794F68675939746A77426B4A70627048345845452F612F777257336833595A656D59644536353063574C5364744447366444667476313148384B4B49306B477949554B52513377483367547531546D38736B3D0A0053484C564C3D3100434C4F554453444B5F434F4E544558545F41574152455F5553455F434C49454E545F43455254494649434154453D74727565004C455353434C4F53453D2F7573722F62696E2F6C6573737069706520257320257300424153485F46554E435F7069703325253D2829207B20202F7573722F62696E2F67706B67207069703320222440220A7D005353485F415554485F534F434B3D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E2F2E7373682F6167656E742F732E3230524D6B6F466350352E737368642E333630383034322E63614837725067566563005445524D3D787465726D2D323536636F6C6F7200424153485F46554E435F706F6574727925253D2829207B20202F7573722F62696E2F67706B6720706F6574727920222440220A7D005348454C4C3D2F62696E2F6261736800434C4F554453444B5F494E5445524E414C5F555345523D7472756500434C4F554453444B5F434F4E544558545F41574152455F43455254494649434154455F434F4E4649475F46494C455F504154483D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004348524F4D455F52454D4F54455F4445534B544F505F44454641554C545F4445534B544F505F53495A45533D3136303078313230302C3338343078323136302C3338343078323536302C3531323078313434302C323136307833383430005844475F53455353494F4E5F545950453D74747900424153485F46554E435F706E707825253D2829207B20202F7573722F62696E2F67706B6720706E707820222440220A7D00424153485F46554E435F707974686F6E3325253D2829207B20202F7573722F62696E2F67706B6720707974686F6E3320222440220A7D00424153485F46554E435F70697025253D2829207B20202F7573722F62696E2F67706B672070697020222440220A7D00424153485F46554E435F7069707825253D2829207B20202F7573722F62696E2F67706B67207069707820222440220A7D004C414E473D656E5F55532E5554462D38005832305F484F4D453D2F676F6F676C652F646174612F72772F75736572732F68612F6861726A6F686E005353485F434F4E4E454354494F4E3D3137322E3235332E33312E323337203437383431203137322E32382E35372E313037203232005844475F52554E54494D455F4449523D2F72756E2F757365722F34393937333200424153485F46554E435F757625253D2829207B20202F7573722F62696E2F67706B6720757620222440220A7D00424153485F46554E435F707974686F6E25253D2829207B20202F7573722F62696E2F67706B6720707974686F6E20222440220A7D00474F4F474C455F4150495F43455254494649434154455F434F4E4649473D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004356535F5253483D73736800505954484F4E504154483D2F7573722F6C6F63616C2F6275696C64746F6F6C732F63757272656E742F73697465637573746F6D697A65005844475F53455353494F4E5F434C4153533D7573657200474F4F474C455F415554485F574542415554484E5F504C5547494E3D67636C6F7564776562617574686E00424153485F46554E435F70646D25253D2829207B20202F7573722F62696E2F67706B672070646D20222440220A7D0053545245414D5A5F534552564552533D5B323030313A343836303A663830323A3A37385D3A3935333000484F4D453D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E005844475F444154415F444952533D2F7573722F73686172652F676E6F6D653A2F7573722F6C6F63616C2F73686172652F3A2F7573722F73686172652F002F746D702F612E6F7574000000000000000000 + - Type: LinuxCPUInfo + Text: | + processor : 0 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 0 + cpu cores : 12 + apicid : 0 + initial apicid : 0 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 1 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 1 + cpu cores : 12 + apicid : 2 + initial apicid : 2 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 2 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 2 + cpu cores : 12 + apicid : 4 + initial apicid : 4 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 3 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 3 + cpu cores : 12 + apicid : 6 + initial apicid : 6 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 4 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 4 + cpu cores : 12 + apicid : 8 + initial apicid : 8 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 5 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 5 + cpu cores : 12 + apicid : 10 + initial apicid : 10 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 6 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 6 + cpu cores : 12 + apicid : 12 + initial apicid : 12 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 7 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 7 + cpu cores : 12 + apicid : 14 + initial apicid : 14 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 8 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 8 + cpu cores : 12 + apicid : 16 + initial apicid : 16 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 9 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 9 + cpu cores : 12 + apicid : 18 + initial apicid : 18 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 10 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 10 + cpu cores : 12 + apicid : 20 + initial apicid : 20 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 11 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 11 + cpu cores : 12 + apicid : 22 + initial apicid : 22 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 12 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 0 + cpu cores : 12 + apicid : 1 + initial apicid : 1 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 13 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 1 + cpu cores : 12 + apicid : 3 + initial apicid : 3 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 14 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 2 + cpu cores : 12 + apicid : 5 + initial apicid : 5 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 15 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 3 + cpu cores : 12 + apicid : 7 + initial apicid : 7 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 16 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 4 + cpu cores : 12 + apicid : 9 + initial apicid : 9 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 17 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 5 + cpu cores : 12 + apicid : 11 + initial apicid : 11 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 18 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 6 + cpu cores : 12 + apicid : 13 + initial apicid : 13 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 19 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 7 + cpu cores : 12 + apicid : 15 + initial apicid : 15 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 20 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 8 + cpu cores : 12 + apicid : 17 + initial apicid : 17 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 21 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 9 + cpu cores : 12 + apicid : 19 + initial apicid : 19 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 22 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 10 + cpu cores : 12 + apicid : 21 + initial apicid : 21 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + processor : 23 + vendor_id : AuthenticAMD + cpu family : 23 + model : 49 + model name : AMD EPYC 7B12 + stepping : 0 + microcode : 0xffffffff + cpu MHz : 2249.998 + cache size : 512 KB + physical id : 0 + siblings : 24 + core id : 11 + cpu cores : 12 + apicid : 23 + initial apicid : 23 + fpu : yes + fpu_exception : yes + cpuid level : 13 + wp : yes + flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt nrip_save umip rdpid + bugs : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb srso ibpb_no_ret spectre_v2_user + bogomips : 4499.99 + TLB size : 3072 4K pages + clflush size : 64 + cache_alignment : 64 + address sizes : 48 bits physical, 48 bits virtual + power management: + + - Type: LinuxLSBRelease + Text: | + # $Id: //depot/google3/googledata/corp/puppet/goobuntu/common/modules/base/templates/lsb-release.erb#9 $ + DISTRIB_CODENAME=rodete + DISTRIB_DESCRIPTION="Debian GNU/Linux rodete" + DISTRIB_ID=Debian + DISTRIB_RELEASE=rodete + GOOGLE_CODENAME=rodete + GOOGLE_ID=Goobuntu + GOOGLE_RELEASE="rodete 20260210.05.04RD" + GOOGLE_ROLE=desktop + GOOGLE_TRACK=stable + - Type: LinuxProcStatus + Text: | + Name: a.out + Umask: 0027 + State: t (tracing stop) + Tgid: 3616167 + Ngid: 0 + Pid: 3616167 + PPid: 3616128 + TracerPid: 3616128 + Uid: 499732 499732 499732 499732 + Gid: 89939 89939 89939 89939 + FDSize: 64 + Groups: 996 5000 66688 70967 70970 75209 77056 79910 79982 81448 82072 82189 82193 82712 83042 83243 84796 85841 86035 86931 87465 87558 87815 87986 88414 89046 89266 89275 89939 89971 90128 90338 90384 90387 90415 90518 90537 90558 90578 90673 90680 90899 90968 91041 91199 91674 91675 91750 91952 92188 92278 92487 92592 92741 92930 93214 93296 93298 93368 93703 93719 93743 93858 94083 94191 94278 94317 94330 94331 94332 94333 94334 94335 94336 94337 94338 94339 94340 94341 94342 94343 94344 94376 95521 96089 96577 96792 96853 97231 97552 97622 97644 97829 98356 98646 98661 99309 99388 99553 99567 99581 100113 100161 100283 100286 100405 100870 101193 101387 101389 101457 101493 102050 102136 102535 102941 103080 103090 103091 103093 103096 103121 103125 103142 103143 103175 103289 103291 103293 103295 103304 103306 103320 103323 103328 103343 103345 103411 103421 103462 103464 103465 103541 103568 103580 103587 103588 103596 103631 103654 103673 103745 + NStgid: 3616167 + NSpid: 3616167 + NSpgid: 3616167 + NSsid: 3608050 + Kthread: 0 + VmPeak: 2528 kB + VmSize: 2440 kB + VmLck: 0 kB + VmPin: 0 kB + VmHWM: 1216 kB + VmRSS: 1216 kB + RssAnon: 104 kB + RssFile: 1104 kB + RssShmem: 8 kB + VmData: 92 kB + VmStk: 136 kB + VmExe: 4 kB + VmLib: 1596 kB + VmPTE: 32 kB + VmSwap: 0 kB + HugetlbPages: 0 kB + CoreDumping: 0 + THP_enabled: 1 + untag_mask: 0xffffffffffffffff + Threads: 1 + SigQ: 1918/385560 + SigPnd: 0000000000000000 + ShdPnd: 0000000000000000 + SigBlk: 0000000000000000 + SigIgn: 0000000004001000 + SigCgt: 0000000000000000 + CapInh: 0000000000000000 + CapPrm: 0000000000000000 + CapEff: 0000000000000000 + CapBnd: 000001ffffffffff + CapAmb: 0000000000000000 + NoNewPrivs: 0 + Seccomp: 0 + Seccomp_filters: 0 + Speculation_Store_Bypass: thread vulnerable + SpeculationIndirectBranch: conditional enabled + Cpus_allowed: ffffff + Cpus_allowed_list: 0-23 + Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 + Mems_allowed_list: 0 + voluntary_ctxt_switches: 6 + nonvoluntary_ctxt_switches: 0 + x86_Thread_features: + x86_Thread_features_locked: + - Type: LinuxCMDLine + Text: | + /tmp/a.out + - Type: LinuxEnviron + Content: 434C4F554453444B5F434F4E544558545F41574152455F5553455F4543505F485454505F50524F58593D74727565004C4553534F50454E3D7C202F7573722F62696E2F6C6573737069706520257300424153485F46554E435F6E706D25253D2829207B20202F7573722F62696E2F67706B67206E706D20222440220A7D005253594E435F5253483D73736800504152494E49543D72546267715220423D2E3F5F415F6120513D5F733E7C3A004D4F54445F53484F574E3D70616D004C535F434F4C4F52533D72733D303A64693D30313B33343A6C6E3D30313B33363A6D683D30303A70693D34303B33333A736F3D30313B33353A646F3D30313B33353A62643D34303B33333B30313A63643D34303B33333B30313A6F723D34303B33313B30313A6D693D30303A73753D33373B34313A73673D33303B34333A63613D30303A74773D33303B34323A6F773D33343B34323A73743D33373B34343A65783D30313B33323A2A2E377A3D30313B33313A2A2E6163653D30313B33313A2A2E616C7A3D30313B33313A2A2E61706B3D30313B33313A2A2E6172633D30313B33313A2A2E61726A3D30313B33313A2A2E627A3D30313B33313A2A2E627A323D30313B33313A2A2E6361623D30313B33313A2A2E6370696F3D30313B33313A2A2E63726174653D30313B33313A2A2E6465623D30313B33313A2A2E6472706D3D30313B33313A2A2E64776D3D30313B33313A2A2E647A3D30313B33313A2A2E6561723D30313B33313A2A2E6567673D30313B33313A2A2E6573643D30313B33313A2A2E677A3D30313B33313A2A2E6A61723D30313B33313A2A2E6C68613D30313B33313A2A2E6C727A3D30313B33313A2A2E6C7A3D30313B33313A2A2E6C7A343D30313B33313A2A2E6C7A683D30313B33313A2A2E6C7A6D613D30313B33313A2A2E6C7A6F3D30313B33313A2A2E70797A3D30313B33313A2A2E7261723D30313B33313A2A2E72706D3D30313B33313A2A2E727A3D30313B33313A2A2E7361723D30313B33313A2A2E73776D3D30313B33313A2A2E74377A3D30313B33313A2A2E7461723D30313B33313A2A2E74617A3D30313B33313A2A2E74627A3D30313B33313A2A2E74627A323D30313B33313A2A2E74677A3D30313B33313A2A2E746C7A3D30313B33313A2A2E74787A3D30313B33313A2A2E747A3D30313B33313A2A2E747A6F3D30313B33313A2A2E747A73743D30313B33313A2A2E756465623D30313B33313A2A2E7761723D30313B33313A2A2E77686C3D30313B33313A2A2E77696D3D30313B33313A2A2E787A3D30313B33313A2A2E7A3D30313B33313A2A2E7A69703D30313B33313A2A2E7A6F6F3D30313B33313A2A2E7A73743D30313B33313A2A2E617669663D30313B33353A2A2E6A70673D30313B33353A2A2E6A7065673D30313B33353A2A2E6A786C3D30313B33353A2A2E6D6A70673D30313B33353A2A2E6D6A7065673D30313B33353A2A2E6769663D30313B33353A2A2E626D703D30313B33353A2A2E70626D3D30313B33353A2A2E70676D3D30313B33353A2A2E70706D3D30313B33353A2A2E7467613D30313B33353A2A2E78626D3D30313B33353A2A2E78706D3D30313B33353A2A2E7469663D30313B33353A2A2E746966663D30313B33353A2A2E706E673D30313B33353A2A2E7376673D30313B33353A2A2E7376677A3D30313B33353A2A2E6D6E673D30313B33353A2A2E7063783D30313B33353A2A2E6D6F763D30313B33353A2A2E6D70673D30313B33353A2A2E6D7065673D30313B33353A2A2E6D32763D30313B33353A2A2E6D6B763D30313B33353A2A2E7765626D3D30313B33353A2A2E776562703D30313B33353A2A2E6F676D3D30313B33353A2A2E6D70343D30313B33353A2A2E6D34763D30313B33353A2A2E6D7034763D30313B33353A2A2E766F623D30313B33353A2A2E71743D30313B33353A2A2E6E75763D30313B33353A2A2E776D763D30313B33353A2A2E6173663D30313B33353A2A2E726D3D30313B33353A2A2E726D76623D30313B33353A2A2E666C633D30313B33353A2A2E6176693D30313B33353A2A2E666C693D30313B33353A2A2E666C763D30313B33353A2A2E676C3D30313B33353A2A2E646C3D30313B33353A2A2E7863663D30313B33353A2A2E7877643D30313B33353A2A2E7975763D30313B33353A2A2E63676D3D30313B33353A2A2E656D663D30313B33353A2A2E6F67763D30313B33353A2A2E6F67783D30313B33353A2A2E6161633D30303B33363A2A2E61753D30303B33363A2A2E666C61633D30303B33363A2A2E6D34613D30303B33363A2A2E6D69643D30303B33363A2A2E6D6964693D30303B33363A2A2E6D6B613D30303B33363A2A2E6D70333D30303B33363A2A2E6D70633D30303B33363A2A2E6F67673D30303B33363A2A2E72613D30303B33363A2A2E7761763D30303B33363A2A2E6F67613D30303B33363A2A2E6F7075733D30303B33363A2A2E7370783D30303B33363A2A2E787370663D30303B33363A2A7E3D30303B39303A2A233D30303B39303A2A2E62616B3D30303B39303A2A2E6372646F776E6C6F61643D30303B39303A2A2E64706B672D646973743D30303B39303A2A2E64706B672D6E65773D30303B39303A2A2E64706B672D6F6C643D30303B39303A2A2E64706B672D746D703D30303B39303A2A2E6F6C643D30303B39303A2A2E6F7269673D30303B39303A2A2E706172743D30303B39303A2A2E72656A3D30303B39303A2A2E72706D6E65773D30303B39303A2A2E72706D6F7269673D30303B39303A2A2E72706D736176653D30303B39303A2A2E7377703D30303B39303A2A2E746D703D30303B39303A2A2E7563662D646973743D30303B39303A2A2E7563662D6E65773D30303B39303A2A2E7563662D6F6C643D30303B39303A00534B5F5349474E494E475F504C5547494E3D676E756262796167656E7400474F4F474C455F434C4F55445F44495341424C455F4449524543545F504154483D74727565005F3D2F7573722F62696E2F6C6C646200444255535F53455353494F4E5F4255535F414444524553533D756E69783A706174683D2F72756E2F757365722F3439393733322F62757300555345523D6861726A6F686E005353485F434C49454E543D3137322E3235332E33312E323337203437383431203232005034434F4E4649473D2E7034636F6E666967005353485F5454593D2F6465762F7074732F3000424153485F46554E435F7961726E25253D2829207B20202F7573722F62696E2F67706B67207961726E20222440220A7D00424153485F46554E435F6E707825253D2829207B20202F7573722F62696E2F67706B67206E707820222440220A7D0050344D455247453D2F676F6F676C652F7372632F66696C65732F686561642F6465706F742F656E672F706572666F7263652F6D6572676570342E74636C00424153485F46554E435F706E706D25253D2829207B20202F7573722F62696E2F67706B6720706E706D20222440220A7D004C4F474E414D453D6861726A6F686E00434C4F554453444B5F434F4E5441494E45525F5553455F4150504C49434154494F4E5F44454641554C545F43524544454E5449414C533D7472756500424153485F46554E435F686174636825253D2829207B20202F7573722F62696E2F67706B6720686174636820222440220A7D0048495354434F4E54524F4C3D69676E6F72656475707300504154483D2F7573722F6C69622F676F6F676C652D676F6C616E672F62696E3A2F7573722F6C6F63616C2F6275696C64746F6F6C732F6A6176612F6A646B2F62696E3A2F7573722F6C6F63616C2F7362696E3A2F7573722F6C6F63616C2F62696E3A2F7573722F7362696E3A2F7573722F62696E3A2F7362696E3A2F62696E005844475F53455353494F4E5F49443D6339303334005057443D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E00424153485F46554E435F7961726E706B6725253D2829207B20202F7573722F62696E2F67706B67207961726E706B6720222440220A7D005353485F415554485F4B45593D65636473612D736861322D6E697374703235362D636572742D763031406F70656E7373682E636F6D20414141414B47566A5A484E684C584E6F59544974626D6C7A644841794E54597459325679644331324D4446416233426C626E4E7A6143356A623230414141416747477568656C4D7545582B357530682B61516D78456E366B6A50433075574E47494C2B793543766B314F6F4141414149626D6C7A644841794E545941414142424250415938413859644E6A6770617A733930786C70703835623231517841416D6C446A384432444A386976546B7648434B676748742F6759495A32306B6A70665A7142644F6C7437385A6C5674725A42453872344D2B385A4141414145414A7A38774141414145414141415861474679616D396F626B426A62334A774C6D6476623264735A53356A62323041414141644141414142326868636D7076614734414141414F5A3239765A32786C58476868636D70766147344141414141615A335A42514141414142706E764E784141414141414141414D77414141415959325679644331745A5852685A4746305955426E6232396E6247557559323974414141414B67414141435949415249677755464C345761352B4368396B4D7047676F4A764F4F4C5747456E75417759724C5073445A4265427576496742674141414256775A584A7461585174574445784C575A76636E6468636D5270626D634141414141414141414633426C636D3170644331685A3256756443316D62334A3359584A6B6157356E414141414141414141425A775A584A7461585174634739796443316D62334A3359584A6B6157356E4141414141414141414170775A584A7461585174634852354141414141414141414135775A584A746158517464584E6C6369317959774141414141414141414141414142467741414141647A63326774636E4E6841414141417745414151414141514541764E305A533562314F5A59746F4A3150534B59344749776A69733169347A5A5A324D42644E2F544559714A494F56736641746B447268433959475356757961692F6B4F58774C4C6E4663356456445257484C4453427A6F5845676C34514B436D4E75396E6E65562F634D4C4571346430336F3144504F535051474A44712B776570344B3948755277767A6F673677544441354B70306C6F436E5759384D4854627434532F4F32526F356D76463078306563397663637757314B4F74632F4379645169476D6576425A4F514F795874385A435A4B4574534F5449506841453535574B386167744D45734A6C485274637377536732424A4E4A4D5365554B674C31416E2F6F434539624B414D452F7A585659564B354675763465707163636E6433735157325438716E694F4963454449346F796244656A6D3647385650772F707869655350626146476674754C79522F72485335324F68774141415251414141414D636E4E684C584E6F595449744D6A55324141414241477A374C6357654478443770523942723178684E624A73317345744B4D7257736C65775657692F56356A34647A3268484C64384B6C57753467746367356A767370793876594E58454950576C47683037745953695744575869444D575562765544314E514F794E345548686B595576574F2B647A372B4C71776C7A574D515A38796958775234714E4A666B343070666F65424B59384E71726E776A4B52724173446E53656E4B544B4E6F646A73666E684B5A4839784C566663456F544764674831364375625947396C31666D65613750724D37714F7250554F6E6B4B565548736F6475766A6F72475A335063476258536176646E7A467836446A6251726D514462523638794F68675939746A77426B4A70627048345845452F612F777257336833595A656D59644536353063574C5364744447366444667476313148384B4B49306B477949554B52513377483367547531546D38736B3D0A0053484C564C3D3100434C4F554453444B5F434F4E544558545F41574152455F5553455F434C49454E545F43455254494649434154453D74727565004C455353434C4F53453D2F7573722F62696E2F6C6573737069706520257320257300424153485F46554E435F7069703325253D2829207B20202F7573722F62696E2F67706B67207069703320222440220A7D005353485F415554485F534F434B3D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E2F2E7373682F6167656E742F732E3230524D6B6F466350352E737368642E333630383034322E63614837725067566563005445524D3D787465726D2D323536636F6C6F7200424153485F46554E435F706F6574727925253D2829207B20202F7573722F62696E2F67706B6720706F6574727920222440220A7D005348454C4C3D2F62696E2F6261736800434C4F554453444B5F494E5445524E414C5F555345523D7472756500434C4F554453444B5F434F4E544558545F41574152455F43455254494649434154455F434F4E4649475F46494C455F504154483D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004348524F4D455F52454D4F54455F4445534B544F505F44454641554C545F4445534B544F505F53495A45533D3136303078313230302C3338343078323136302C3338343078323536302C3531323078313434302C323136307833383430005844475F53455353494F4E5F545950453D74747900424153485F46554E435F706E707825253D2829207B20202F7573722F62696E2F67706B6720706E707820222440220A7D00424153485F46554E435F707974686F6E3325253D2829207B20202F7573722F62696E2F67706B6720707974686F6E3320222440220A7D00424153485F46554E435F70697025253D2829207B20202F7573722F62696E2F67706B672070697020222440220A7D00424153485F46554E435F7069707825253D2829207B20202F7573722F62696E2F67706B67207069707820222440220A7D004C414E473D656E5F55532E5554462D38005832305F484F4D453D2F676F6F676C652F646174612F72772F75736572732F68612F6861726A6F686E005353485F434F4E4E454354494F4E3D3137322E3235332E33312E323337203437383431203137322E32382E35372E313037203232005844475F52554E54494D455F4449523D2F72756E2F757365722F34393937333200424153485F46554E435F757625253D2829207B20202F7573722F62696E2F67706B6720757620222440220A7D00424153485F46554E435F707974686F6E25253D2829207B20202F7573722F62696E2F67706B6720707974686F6E20222440220A7D00474F4F474C455F4150495F43455254494649434154455F434F4E4649473D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004356535F5253483D73736800505954484F4E504154483D2F7573722F6C6F63616C2F6275696C64746F6F6C732F63757272656E742F73697465637573746F6D697A65005844475F53455353494F4E5F434C4153533D7573657200474F4F474C455F415554485F574542415554484E5F504C5547494E3D67636C6F7564776562617574686E00424153485F46554E435F70646D25253D2829207B20202F7573722F62696E2F67706B672070646D20222440220A7D0053545245414D5A5F534552564552533D5B323030313A343836303A663830323A3A37385D3A3935333000484F4D453D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E005844475F444154415F444952533D2F7573722F73686172652F676E6F6D653A2F7573722F6C6F63616C2F73686172652F3A2F7573722F73686172652F00 + - Type: LinuxAuxv + Content: 21000000000000000050FCF7FF7F00003300000000000000F0060000000000001000000000000000FFFB8B17000000000600000000000000001000000000000011000000000000006400000000000000030000000000000040405555555500000400000000000000380000000000000005000000000000000E0000000000000007000000000000000070FCF7FF7F000008000000000000000000000000000000090000000000000050505555555500000B0000000000000014A00700000000000C0000000000000014A00700000000000D00000000000000535F0100000000000E00000000000000535F01000000000017000000000000000000000000000000190000000000000059D9FFFFFF7F00001A0000000000000002000000000000001F00000000000000EDEFFFFFFF7F00000F0000000000000069D9FFFFFF7F00001B000000000000001C000000000000001C00000000000000200000000000000000000000000000000000000000000000 + - Type: LinuxMaps + Text: | + 555555554000-555555555000 r--p 00000000 00:2c 69154 /tmp/a.out + 555555555000-555555556000 r-xp 00001000 00:2c 69154 /tmp/a.out + 555555556000-555555557000 r--p 00002000 00:2c 69154 /tmp/a.out + 555555557000-555555558000 r--p 00002000 00:2c 69154 /tmp/a.out + 555555558000-555555559000 rw-p 00003000 00:2c 69154 /tmp/a.out + 7ffff7dae000-7ffff7db1000 rw-p 00000000 00:00 0 + 7ffff7db1000-7ffff7dd9000 r--p 00000000 fd:01 11689180 /usr/lib/x86_64-linux-gnu/libc.so.6 + 7ffff7dd9000-7ffff7f3e000 r-xp 00028000 fd:01 11689180 /usr/lib/x86_64-linux-gnu/libc.so.6 + 7ffff7f3e000-7ffff7f94000 r--p 0018d000 fd:01 11689180 /usr/lib/x86_64-linux-gnu/libc.so.6 + 7ffff7f94000-7ffff7f98000 r--p 001e2000 fd:01 11689180 /usr/lib/x86_64-linux-gnu/libc.so.6 + 7ffff7f98000-7ffff7f9a000 rw-p 001e6000 fd:01 11689180 /usr/lib/x86_64-linux-gnu/libc.so.6 + 7ffff7f9a000-7ffff7fa7000 rw-p 00000000 00:00 0 + 7ffff7fbd000-7ffff7fbf000 rw-p 00000000 00:00 0 + 7ffff7fbf000-7ffff7fc3000 r--p 00000000 00:00 0 [vvar] + 7ffff7fc3000-7ffff7fc5000 r--p 00000000 00:00 0 [vvar_vclock] + 7ffff7fc5000-7ffff7fc7000 r-xp 00000000 00:00 0 [vdso] + 7ffff7fc7000-7ffff7fc8000 r--p 00000000 fd:01 11689079 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 + 7ffff7fc8000-7ffff7ff0000 r-xp 00001000 fd:01 11689079 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 + 7ffff7ff0000-7ffff7ffb000 r--p 00029000 fd:01 11689079 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 + 7ffff7ffb000-7ffff7ffd000 r--p 00034000 fd:01 11689079 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 + 7ffff7ffd000-7ffff7ffe000 rw-p 00036000 fd:01 11689079 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 + 7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 + 7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack] + - Type: LinuxProcStat + Text: | + 3616167 (a.out) t 3616128 3616167 3608050 34816 3615736 0 120 0 0 0 0 0 0 0 20 0 1 0 126326383 2498560 213 18446744073709551615 93824992235520 93824992236013 140737488344560 0 0 0 0 67112960 0 1 0 0 17 1 0 0 0 0 0 93824992247248 93824992247832 93824992251904 140737488345465 140737488345476 140737488345476 140737488351213 0 - Type: Exception - Thread ID: 0x7E03 + Thread ID: 0x372DA7 Exception Record: - Exception Code: 0xB - Exception Address: 0x40011C - Thread Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700100000000000FFFFFFFF0000FFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E8150B24FC7F0000E8150B24FC7F00000C014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Exception Code: 0x2 + Exception Flags: 0x4C4C4442 + Exception Address: 0x555555555148 + Number of Parameters: 1 + Parameter 0: 0x696F706B61657262 + Parameter 1: 0x312E3120746E + Thread Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700108000000000330000000000000000002B00020200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E40D87D55555555000008D6FFFFFF7F0000F8D5FFFFFF7F0000A0D4FFFFFF7F0000A0D4FFFFFF7F0000F8D5FFFFFF7F0000B0D4FFFFFF7F0000000000000000000080BCFCF7FF7F000020D2FFFFFF7F00000202000000000000000000000000000008D6FFFFFF7F000000D0FFF7FF7F0000D87D5555555500004851555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040E7DAF7FF7F00000000000000000000 - Type: MemoryList Memory Ranges: - - Start of Memory Range: 0x7FFC240B1568 - Content: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006218160B24FC7F000042014000000000000C0140000000000000000000000000000000000000000000000000000000006638160B24FC7F00005F014000000000000000000000000000000000000000005F0000000000000000010000000000000002200B24FC7F00000000000000000000FE2F0B24FC7F00000000000000000000210000000000000000901224FC7F00001000000000000000FFFBEBBF0000000006000000000000000010000000000000110000000000000064000000000000000300000000000000400040000000000004000000000000003800000000000000050000000000000003000000000000000700000000000000000000000000000008000000000000000000000000000000090000000000000044014000000000000B0000000000000000000000000000000C0000000000000000000000000000000D0000000000000000000000000000000E000000000000000000000000000000170000000000000000000000000000001900000000000000A9170B24FC7F00001A0000000000000000000000000000001F00000000000000FC3F0B24FC7F00000F00000000000000B9170B24FC7F000000000000000000000000000000000000000AB340B9514A4C453C3FB52168ADE70E7838365F36340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574005F3D2F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574002F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F746573742F612E6F7574000000000000000000 - - Start of Memory Range: 0x400000 - Content: 7F454C4602010100000000000000000002003E000100000044014000000000004000000000000000F0040000000000000000000040003800030040000D000A000100000005000000000000000000000000004000000000000000400000000000E001000000000000E00100000000000000002000000000000400000004000000E800000000000000E800400000000000E80040000000000024000000000000002400000000000000040000000000000051E5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000040000001400000003000000474E550001DF54A6045E657D3F8FFB9CE111878914F8BD6D554889E548897DE8C645FF62488B45E8C6002F5DC3554889E54883EC2048897DE8488975E0C645FF66488B55E8488B45E04889D7FFD0C9C3554889E54883EC10C645FF5FBE0C014000BF00000000E8C2FFFFFFC9C3000000000000001400000000000000017A5200017810011B0C0708900100001C0000001C00000084FFFFFF1500000000410E108602430D06500C07080000001C0000003C00000079FFFFFF2300000000410E108602430D065E0C07080000001C0000005C0000007CFFFFFF1D00000000410E108602430D06580C07080000004743433A20285562756E747520342E382E342D327562756E7475317E31342E30342920342E382E34002C0000000200000000000800000000000C01400000000000550000000000000000000000000000000000000000000000EC00000004000000000008011300000001070000003F0000000C01400000000000550000000000000000000000026261720001010C014000000000001500000000000000019C65000000030E00000001016500000002915804460001036B00000002916F0005086B0000000601065800000007666F6F00010721014000000000002300000000000000019CB8000000030E00000001076500000002915803000000000107C300000002915004460001096B00000002916F0008C30000000965000000000508B80000000A51000000010D44014000000000001D00000000000000019C044600010F6B00000002916F0000011101250E130B030E1B0E1101120710170000022E0103083A0B3B0B271911011207401897421901130000030500030E3A0B3B0B49130218000004340003083A0B3B0B491302180000050F000B0B491300000624000B0B3E0B030E0000072E0103083A0B3B0B271911011207401896421901130000081501271901130000090500491300000A2E013F19030E3A0B3B0B27191101120740189642190000003F00000002001D0000000101FB0E0D000101010100000001000001006D61696E2E6300000000000009020C0140000000000013834B7531F34BC931834BE50202000101626F6F6D6572006D61696E2E6300626F6F6D00474E55204320342E382E34202D6D74756E653D67656E65726963202D6D617263683D7838362D3634202D67002F686F6D652F6C61626174682F74657374005F7374617274006368617200002E73796D746162002E737472746162002E7368737472746162002E6E6F74652E676E752E6275696C642D6964002E74657874002E65685F6672616D65002E636F6D6D656E74002E64656275675F6172616E676573002E64656275675F696E666F002E64656275675F616262726576002E64656275675F6C696E65002E64656275675F737472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B000000070000000200000000000000E800400000000000E80000000000000024000000000000000000000000000000040000000000000000000000000000002E0000000100000006000000000000000C014000000000000C010000000000005500000000000000000000000000000001000000000000000000000000000000340000000100000002000000000000006801400000000000680100000000000078000000000000000000000000000000080000000000000000000000000000003E0000000100000030000000000000000000000000000000E0010000000000002900000000000000000000000000000001000000000000000100000000000000470000000100000000000000000000000000000000000000090200000000000030000000000000000000000000000000010000000000000000000000000000005600000001000000000000000000000000000000000000003902000000000000F00000000000000000000000000000000100000000000000000000000000000062000000010000000000000000000000000000000000000029030000000000009E00000000000000000000000000000001000000000000000000000000000000700000000100000000000000000000000000000000000000C70300000000000043000000000000000000000000000000010000000000000000000000000000007C00000001000000300000000000000000000000000000000A040000000000005D00000000000000000000000000000001000000000000000100000000000000110000000300000000000000000000000000000000000000670400000000000087000000000000000000000000000000010000000000000000000000000000000100000002000000000000000000000000000000000000003008000000000000B0010000000000000C0000000E00000008000000000000001800000000000000090000000300000000000000000000000000000000000000E0090000000000002F000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000100E800400000000000000000000000000000000000030002000C014000000000000000000000000000000000000300030068014000000000000000000000000000000000000300040000000000000000000000000000000000000000000300050000000000000000000000000000000000000000000300060000000000000000000000000000000000000000000300070000000000000000000000000000000000000000000300080000000000000000000000000000000000000000000300090000000000000000000000000000000000010000000400F1FF0000000000000000000000000000000008000000020002000C0140000000000015000000000000000C0000000200020021014000000000002300000000000000000000000400F1FF00000000000000000000000000000000100000001200020044014000000000001D000000000000001700000010000300001060000000000000000000000000002300000010000300001060000000000000000000000000002A0000001000030000106000000000000000000000000000006D61696E2E630062617200666F6F005F7374617274005F5F6273735F7374617274005F6564617461005F656E6400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - - Start of Memory Range: 0x7FFC24126000 - Content: '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' - - Start of Memory Range: 0x7FFC24129000 - Content: 7F454C4602010100000000000000000003003E000100000060060000000000004000000000000000D80A00000000000000000000400038000400400010000F0001000000050000000000000000000000000000000000000000000000000000000C0A0000000000000C0A00000000000000100000000000000200000004000000A003000000000000A003000000000000A0030000000000001001000000000000100100000000000008000000000000000400000004000000B004000000000000B004000000000000B00400000000000068000000000000006800000000000000040000000000000050E57464040000001805000000000000180500000000000018050000000000003C000000000000003C000000000000000400000000000000030000000C000000060000000500000008000000000000000000000009000000020000000A000000000000000B0000000100000007000000000000000300000004000000000000000300000001000000010000000600000089343805466500A10100000007000000090000007E55DD7100CA1BB0DA109A9E528F3068864B85E60D8E1E8294789E7C19A3436E8A2AC62626B062656D5887FF0000000000000000000000000000000000000000000000002800000022000B007008000000000000AC000000000000000100000012000B00D00700000000000088000000000000003D00000022000B00200900000000000048000000000000003600000012000B00200900000000000048000000000000000800000022000B00D00700000000000088000000000000001500000012000B00600800000000000010000000000000001C00000022000B00600800000000000010000000000000002100000012000B007008000000000000AC00000000000000680000001100F1FF000000000000000000000000000000004A00000012000B00700900000000000025000000000000005100000022000B0070090000000000002500000000000000005F5F7664736F5F67657474696D656F66646179005F5F7664736F5F74696D65005F5F7664736F5F636C6F636B5F67657474696D65005F5F7664736F5F636C6F636B5F676574726573005F5F7664736F5F676574637075006C696E75782D7664736F2E736F2E31004C494E55585F322E36000000020002000200020002000200020002000200020002000000000000000100010001000100A1BFEE0D140000001C00000058000000000000000100000002000100F675AE03140000000000000068000000000000000E0000000000000058000000000000001000000000000000000000000000000004000000000000002001000000000000F5FEFF6F0000000068010000000000000500000000000000D8020000000000000600000000000000B8010000000000000A0000000000000072000000000000000B000000000000001800000000000000FCFFFF6F000000006803000000000000FDFFFF6F000000000200000000000000F0FFFF6F000000004A030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000004000000000000004C696E75780000000D0505000600000017000000000100004C696E7578000000352E352E31332D3230302E666333312E7838365F36340000040000001400000003000000474E55008CBE1E6C351152C0C43E68C4EF417DB4C77E8EBD011B033B3C000000060000004801000058000000B80200009800000048030000D000000058030000E4000000080400001C0100005804000030010000000000001400000000000000017A5200017810011B0C0708900100003C0000001C000000E80000006E01000000410E108602540D06458D038C048305630AC347CC42CD41C60C0708410B025B0AC342CC45CD41C60C0708460B000000340000005C000000180200008800000000410E108602430D06428C0348830402490AC342CC41C60C0708410B520AC342CC41C60C0708410B100000009400000070020000100000000000000034000000A80000006C020000AC00000000410E108602430D06428D03458C04730ACC44CD41C60C0708410B480ACC49CD41C60C0708410B0010000000E0000000E4020000480000000000000010000000F400000020030000250000000000000000000000554863F64989D24989C948C1E6044C8D04374889E54155415453EB02F3908B3740F6C60175F68B470483F801741A83F8020F84BA00000083F80374755BB8FFFFFFFF415C415D5DC30F01F9669048C1E2204809C2498B4028488B4F084885D278DB448B5F184839D1730A4829CA490FAFD34801D08B4F1C4D8B58208B1739F2759D48D3E8483DFFC99A3B761631D2482D00CA9A3B83C201483DFFC99A3B77EF4901D35B415C4D891A415D5D49890131C0C34C8D25E8E8FFFF418B1C2485DB0F8478FFFFFF4C8B2DDDE8FFFF4C8B1DDEE8FFFF0F01F96690418B0C2439CB75D948C1E2204809D049F7E54C01DAE963FFFFFF8B15A9D8FFFF488D1DA2D8FFFF83E2FE4189D3F605B2D8FFFF010F842BFFFFFF0F01F9669048C1E2204809C24889D00FBE1595D8FFFF482B057AD8FFFF4989C489D1F7D949D3EC89D148D3E085D24C89E28B0D70D8FFFF480F49D04889D048F7E1480FACD020488B0D52D8FFFF8B134139D37599488D1408E9E6FEFFFF6690554889E541544989F4534883EC104885FF74384889FB488D55E0488D4DE831F6488D3D89C8FFFFE864FEFFFF85C0752B488B45E04889038B45E84869C0D34D621048C1E82689C04889430831C04D85E4751F4883C4105B415C5DC34889DF4C89E6B8600000000F054883C4105B415C5DC38B1519C9FFFF418914248B1513C9FFFF4189542404EBCA0F1F840000000000488B0539C8FFFF4885FF7403488907C3554889E541554989F541544189FC83FF0F7731B80100000089F9D3E0A9830800007434488D4E084889F289FE488D3DDDC7FFFFE8B8FDFFFF85C07508415C31C0415D5DC34489E74C89EE415CB8E40000000F05415D5DC3A860751BA81074E5488D4E084889F289FE488D3D91C8FFFFE87CFDFFFFEBC24863CF488D1590C7FFFF4883C10248C1E1044801D1EB02F3908B02A80175F8488B3149897500488B7108498975088B3239F07492EBE30F1F400083FF0F7731B80100000089F98B1536C8FFFFD3E0A98308000074134885F6742548C7060000000031C048895608C3A860750CA81075E5B8E50000000F05C3BA40420F00EBD631C0C39090909090909090B87B0000000F03C0904885FF740A89C281E2FF0F000089174885F67405C1E80C890631C0C313FDFFFF57000000720005050306FDFFFF4F0000003B0005030383FDFFFF45000000720005050376FDFFFF3D0000003B00050303A8FDFFFF3300000072000505039BFDFFFF2B0000003B0005030392FFFFFF2100000016020404010FAEE80F310F01F90FAEE80F310F01F90FAEE80F310F01F9F30FC7F84743433A2028474E552920392E322E3120323031393038323720285265642048617420392E322E312D312900002E7368737472746162002E676E752E68617368002E64796E73796D002E64796E737472002E676E752E76657273696F6E002E676E752E76657273696F6E5F64002E64796E616D6963002E6E6F7465002E65685F6672616D655F686472002E65685F6672616D65002E74657874002E616C74696E737472756374696F6E73002E616C74696E7374725F7265706C6163656D656E74002E636F6D6D656E74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0000000500000002000000000000002001000000000000200100000000000044000000000000000300000000000000080000000000000004000000000000000B000000F6FFFF6F0200000000000000680100000000000068010000000000005000000000000000030000000000000008000000000000000000000000000000150000000B0000000200000000000000B801000000000000B80100000000000020010000000000000400000001000000080000000000000018000000000000001D000000030000000200000000000000D802000000000000D802000000000000720000000000000000000000000000000100000000000000000000000000000025000000FFFFFF6F02000000000000004A030000000000004A03000000000000180000000000000003000000000000000200000000000000020000000000000032000000FDFFFF6F020000000000000068030000000000006803000000000000380000000000000004000000020000000800000000000000000000000000000041000000060000000300000000000000A003000000000000A00300000000000010010000000000000400000000000000080000000000000010000000000000004A000000070000000200000000000000B004000000000000B004000000000000680000000000000000000000000000000400000000000000000000000000000050000000010000000200000000000000180500000000000018050000000000003C000000000000000000000000000000040000000000000000000000000000005E000000010000000200000000000000580500000000000058050000000000000401000000000000000000000000000008000000000000000000000000000000680000000100000006000000000000006006000000000000600600000000000035030000000000000000000000000000100000000000000000000000000000006E000000010000000200000000000000950900000000000095090000000000005B000000000000000000000000000000010000000000000000000000000000007F000000010000000600000000000000F009000000000000F0090000000000001C000000000000000000000000000000010000000000000000000000000000009500000001000000300000000000000000000000000000000C0A0000000000002C00000000000000000000000000000001000000000000000100000000000000010000000300000000000000000000000000000000000000380A0000000000009E000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - - Start of Memory Range: 0xFFFFFFFFFF600000 - Content: 48C7C0600000000F05C3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC48C7C0C90000000F05C3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC48C7C0350100000F05C3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + - Start of Memory Range: 0x7FFFFFFFD420 + Content: 0000C000000000000000C0000000000000010000000000000000C0000000000040000000000000001000000000000000000008000000000029018C2100000000170000000000000000000000000000000000000000000000000000000000000017000000310000000000000000000000B0D4FFFFFF7F00000000000000000000E0D4FFFFFF7F0000CB515555555500000000000000001440000000000000144000000000000039400000000000003E40F8D5FFFFFF7F000001000000000000000100000000000000A8ACDDF7FF7F0000E0D5FFFFFF7F000080515555555500004040555501000000F8D5FFFFFF7F0000F8D5FFFFFF7F00005002D40952A1CA98000000000000000008D6FFFFFF7F000000D0FFF7FF7F0000D87D555555550000500236A0AD5E356750021651E94E3567000000000000000000000000000000000000000000000000F8D5FFFFFF7F00000100000000000000007B97470D7B2415F0D5FFFFFF7F000065ADDDF7FF7F00008051555555550000D87D55555555000010E3FFF7FF7F0000000000000000000000000000000000005050555555550000F0D5FFFFFF7F0000000000000000000000000000000000007150555555550000E8D5FFFFFF7F00003800000000000000010000000000000079D9FFFFFF7F0000000000000000000084D9FFFFFF7F0000B3D9FFFFFF7F0000D3D9FFFFFF7F000002DAFFFFFF7F000010DAFFFFFF7F000030DAFFFFFF7F00003FDAFFFFFF7F0000BCE1FFFFFF7F0000DAE1FFFFFF7F000000E2FFFFFF7F000010E2FFFFFF7F000048E2FFFFFF7F000055E2FFFFFF7F000078E2FFFFFF7F00008BE2FFFFFF7F00009EE2FFFFFF7F0000CFE2FFFFFF7F0000FEE2FFFFFF7F00003CE3FFFFFF7F00006DE3FFFFFF7F00007DE3FFFFFF7F0000B9E3FFFFFF7F0000ECE3FFFFFF7F000003E4FFFFFF7F000083E4FFFFFF7F000098E4FFFFFF7F0000BBE4FFFFFF7F0000F2E4FFFFFF7F000086EAFFFFFF7F00008EEAFFFFFF7F0000C1EAFFFFFF7F0000E3EAFFFFFF7F000014EBFFFFFF7F000071EBFFFFFF7F000085EBFFFFFF7F0000BAEBFFFFFF7F0000CAEBFFFFFF7F0000E6EBFFFFFF7F00003EECFFFFFF7F00009CECFFFFFF7F0000B1ECFFFFFF7F0000E2ECFFFFFF7F000019EDFFFFFF7F000048EDFFFFFF7F000079EDFFFFFF7F00008AEDFFFFFF7F0000B4EDFFFFFF7F0000E9EDFFFFFF7F00000AEEFFFFFF7F000037EEFFFFFF7F00006CEEFFFFFF7F0000AEEEFFFFFF7F0000BAEEFFFFFF7F0000F1EEFFFFFF7F000008EFFFFFFF7F000033EFFFFFFF7F000062EFFFFFFF7F00008CEFFFFFFF7F0000B0EFFFFFFF7F0000000000000000000021000000000000000050FCF7FF7F00003300000000000000F0060000000000001000000000000000FFFB8B17000000000600000000000000001000000000000011000000000000006400000000000000030000000000000040405555555500000400000000000000380000000000000005000000000000000E0000000000000007000000000000000070FCF7FF7F000008000000000000000000000000000000090000000000000050505555555500000B0000000000000014A00700000000000C0000000000000014A00700000000000D00000000000000535F0100000000000E00000000000000535F01000000000017000000000000000000000000000000190000000000000059D9FFFFFF7F00001A0000000000000002000000000000001F00000000000000EDEFFFFFFF7F00000F0000000000000069D9FFFFFF7F00001B000000000000001C000000000000001C0000000000000020000000000000000000000000000000000000000000000000C27B97470D7B2415EB04A950654C28017838365F3634000000000000000000002F746D702F612E6F757400434C4F554453444B5F434F4E544558545F41574152455F5553455F4543505F485454505F50524F58593D74727565004C4553534F50454E3D7C202F7573722F62696E2F6C6573737069706520257300424153485F46554E435F6E706D25253D2829207B20202F7573722F62696E2F67706B67206E706D20222440220A7D005253594E435F5253483D73736800504152494E49543D72546267715220423D2E3F5F415F6120513D5F733E7C3A004D4F54445F53484F574E3D70616D004C535F434F4C4F52533D72733D303A64693D30313B33343A6C6E3D30313B33363A6D683D30303A70693D34303B33333A736F3D30313B33353A646F3D30313B33353A62643D34303B33333B30313A63643D34303B33333B30313A6F723D34303B33313B30313A6D693D30303A73753D33373B34313A73673D33303B34333A63613D30303A74773D33303B34323A6F773D33343B34323A73743D33373B34343A65783D30313B33323A2A2E377A3D30313B33313A2A2E6163653D30313B33313A2A2E616C7A3D30313B33313A2A2E61706B3D30313B33313A2A2E6172633D30313B33313A2A2E61726A3D30313B33313A2A2E627A3D30313B33313A2A2E627A323D30313B33313A2A2E6361623D30313B33313A2A2E6370696F3D30313B33313A2A2E63726174653D30313B33313A2A2E6465623D30313B33313A2A2E6472706D3D30313B33313A2A2E64776D3D30313B33313A2A2E647A3D30313B33313A2A2E6561723D30313B33313A2A2E6567673D30313B33313A2A2E6573643D30313B33313A2A2E677A3D30313B33313A2A2E6A61723D30313B33313A2A2E6C68613D30313B33313A2A2E6C727A3D30313B33313A2A2E6C7A3D30313B33313A2A2E6C7A343D30313B33313A2A2E6C7A683D30313B33313A2A2E6C7A6D613D30313B33313A2A2E6C7A6F3D30313B33313A2A2E70797A3D30313B33313A2A2E7261723D30313B33313A2A2E72706D3D30313B33313A2A2E727A3D30313B33313A2A2E7361723D30313B33313A2A2E73776D3D30313B33313A2A2E74377A3D30313B33313A2A2E7461723D30313B33313A2A2E74617A3D30313B33313A2A2E74627A3D30313B33313A2A2E74627A323D30313B33313A2A2E74677A3D30313B33313A2A2E746C7A3D30313B33313A2A2E74787A3D30313B33313A2A2E747A3D30313B33313A2A2E747A6F3D30313B33313A2A2E747A73743D30313B33313A2A2E756465623D30313B33313A2A2E7761723D30313B33313A2A2E77686C3D30313B33313A2A2E77696D3D30313B33313A2A2E787A3D30313B33313A2A2E7A3D30313B33313A2A2E7A69703D30313B33313A2A2E7A6F6F3D30313B33313A2A2E7A73743D30313B33313A2A2E617669663D30313B33353A2A2E6A70673D30313B33353A2A2E6A7065673D30313B33353A2A2E6A786C3D30313B33353A2A2E6D6A70673D30313B33353A2A2E6D6A7065673D30313B33353A2A2E6769663D30313B33353A2A2E626D703D30313B33353A2A2E70626D3D30313B33353A2A2E70676D3D30313B33353A2A2E70706D3D30313B33353A2A2E7467613D30313B33353A2A2E78626D3D30313B33353A2A2E78706D3D30313B33353A2A2E7469663D30313B33353A2A2E746966663D30313B33353A2A2E706E673D30313B33353A2A2E7376673D30313B33353A2A2E7376677A3D30313B33353A2A2E6D6E673D30313B33353A2A2E7063783D30313B33353A2A2E6D6F763D30313B33353A2A2E6D70673D30313B33353A2A2E6D7065673D30313B33353A2A2E6D32763D30313B33353A2A2E6D6B763D30313B33353A2A2E7765626D3D30313B33353A2A2E776562703D30313B33353A2A2E6F676D3D30313B33353A2A2E6D70343D30313B33353A2A2E6D34763D30313B33353A2A2E6D7034763D30313B33353A2A2E766F623D30313B33353A2A2E71743D30313B33353A2A2E6E75763D30313B33353A2A2E776D763D30313B33353A2A2E6173663D30313B33353A2A2E726D3D30313B33353A2A2E726D76623D30313B33353A2A2E666C633D30313B33353A2A2E6176693D30313B33353A2A2E666C693D30313B33353A2A2E666C763D30313B33353A2A2E676C3D30313B33353A2A2E646C3D30313B33353A2A2E7863663D30313B33353A2A2E7877643D30313B33353A2A2E7975763D30313B33353A2A2E63676D3D30313B33353A2A2E656D663D30313B33353A2A2E6F67763D30313B33353A2A2E6F67783D30313B33353A2A2E6161633D30303B33363A2A2E61753D30303B33363A2A2E666C61633D30303B33363A2A2E6D34613D30303B33363A2A2E6D69643D30303B33363A2A2E6D6964693D30303B33363A2A2E6D6B613D30303B33363A2A2E6D70333D30303B33363A2A2E6D70633D30303B33363A2A2E6F67673D30303B33363A2A2E72613D30303B33363A2A2E7761763D30303B33363A2A2E6F67613D30303B33363A2A2E6F7075733D30303B33363A2A2E7370783D30303B33363A2A2E787370663D30303B33363A2A7E3D30303B39303A2A233D30303B39303A2A2E62616B3D30303B39303A2A2E6372646F776E6C6F61643D30303B39303A2A2E64706B672D646973743D30303B39303A2A2E64706B672D6E65773D30303B39303A2A2E64706B672D6F6C643D30303B39303A2A2E64706B672D746D703D30303B39303A2A2E6F6C643D30303B39303A2A2E6F7269673D30303B39303A2A2E706172743D30303B39303A2A2E72656A3D30303B39303A2A2E72706D6E65773D30303B39303A2A2E72706D6F7269673D30303B39303A2A2E72706D736176653D30303B39303A2A2E7377703D30303B39303A2A2E746D703D30303B39303A2A2E7563662D646973743D30303B39303A2A2E7563662D6E65773D30303B39303A2A2E7563662D6F6C643D30303B39303A00534B5F5349474E494E475F504C5547494E3D676E756262796167656E7400474F4F474C455F434C4F55445F44495341424C455F4449524543545F504154483D74727565005F3D2F7573722F62696E2F6C6C646200444255535F53455353494F4E5F4255535F414444524553533D756E69783A706174683D2F72756E2F757365722F3439393733322F62757300555345523D6861726A6F686E005353485F434C49454E543D3137322E3235332E33312E323337203437383431203232005034434F4E4649473D2E7034636F6E666967005353485F5454593D2F6465762F7074732F3000424153485F46554E435F7961726E25253D2829207B20202F7573722F62696E2F67706B67207961726E20222440220A7D00424153485F46554E435F6E707825253D2829207B20202F7573722F62696E2F67706B67206E707820222440220A7D0050344D455247453D2F676F6F676C652F7372632F66696C65732F686561642F6465706F742F656E672F706572666F7263652F6D6572676570342E74636C00424153485F46554E435F706E706D25253D2829207B20202F7573722F62696E2F67706B6720706E706D20222440220A7D004C4F474E414D453D6861726A6F686E00434C4F554453444B5F434F4E5441494E45525F5553455F4150504C49434154494F4E5F44454641554C545F43524544454E5449414C533D7472756500424153485F46554E435F686174636825253D2829207B20202F7573722F62696E2F67706B6720686174636820222440220A7D0048495354434F4E54524F4C3D69676E6F72656475707300504154483D2F7573722F6C69622F676F6F676C652D676F6C616E672F62696E3A2F7573722F6C6F63616C2F6275696C64746F6F6C732F6A6176612F6A646B2F62696E3A2F7573722F6C6F63616C2F7362696E3A2F7573722F6C6F63616C2F62696E3A2F7573722F7362696E3A2F7573722F62696E3A2F7362696E3A2F62696E005844475F53455353494F4E5F49443D6339303334005057443D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E00424153485F46554E435F7961726E706B6725253D2829207B20202F7573722F62696E2F67706B67207961726E706B6720222440220A7D005353485F415554485F4B45593D65636473612D736861322D6E697374703235362D636572742D763031406F70656E7373682E636F6D20414141414B47566A5A484E684C584E6F59544974626D6C7A644841794E54597459325679644331324D4446416233426C626E4E7A6143356A623230414141416747477568656C4D7545582B357530682B61516D78456E366B6A50433075574E47494C2B793543766B314F6F4141414149626D6C7A644841794E545941414142424250415938413859644E6A6770617A733930786C70703835623231517841416D6C446A384432444A386976546B7648434B676748742F6759495A32306B6A70665A7142644F6C7437385A6C5674725A42453872344D2B385A4141414145414A7A38774141414145414141415861474679616D396F626B426A62334A774C6D6476623264735A53356A62323041414141644141414142326868636D7076614734414141414F5A3239765A32786C58476868636D70766147344141414141615A335A42514141414142706E764E784141414141414141414D77414141415959325679644331745A5852685A4746305955426E6232396E6247557559323974414141414B67414141435949415249677755464C345761352B4368396B4D7047676F4A764F4F4C5747456E75417759724C5073445A4265427576496742674141414256775A584A7461585174574445784C575A76636E6468636D5270626D634141414141414141414633426C636D3170644331685A3256756443316D62334A3359584A6B6157356E414141414141414141425A775A584A7461585174634739796443316D62334A3359584A6B6157356E4141414141414141414170775A584A7461585174634852354141414141414141414135775A584A746158517464584E6C6369317959774141414141414141414141414142467741414141647A63326774636E4E6841414141417745414151414141514541764E305A533562314F5A59746F4A3150534B59344749776A69733169347A5A5A324D42644E2F544559714A494F56736641746B447268433959475356757961692F6B4F58774C4C6E4663356456445257484C4453427A6F5845676C34514B436D4E75396E6E65562F634D4C4571346430336F3144504F535051474A44712B776570344B3948755277767A6F673677544441354B70306C6F436E5759384D4854627434532F4F32526F356D76463078306563397663637757314B4F74632F4379645169476D6576425A4F514F795874385A435A4B4574534F5449506841453535574B386167744D45734A6C485274637377536732424A4E4A4D5365554B674C31416E2F6F434539624B414D452F7A585659564B354675763465707163636E6433735157325438716E694F4963454449346F796244656A6D3647385650772F707869655350626146476674754C79522F72485335324F68774141415251414141414D636E4E684C584E6F595449744D6A55324141414241477A374C6357654478443770523942723178684E624A73317345744B4D7257736C65775657692F56356A34647A3268484C64384B6C57753467746367356A767370793876594E58454950576C47683037745953695744575869444D575562765544314E514F794E345548686B595576574F2B647A372B4C71776C7A574D515A38796958775234714E4A666B343070666F65424B59384E71726E776A4B52724173446E53656E4B544B4E6F646A73666E684B5A4839784C566663456F544764674831364375625947396C31666D65613750724D37714F7250554F6E6B4B565548736F6475766A6F72475A335063476258536176646E7A467836446A6251726D514462523638794F68675939746A77426B4A70627048345845452F612F777257336833595A656D59644536353063574C5364744447366444667476313148384B4B49306B477949554B52513377483367547531546D38736B3D0A0053484C564C3D3100434C4F554453444B5F434F4E544558545F41574152455F5553455F434C49454E545F43455254494649434154453D74727565004C455353434C4F53453D2F7573722F62696E2F6C6573737069706520257320257300424153485F46554E435F7069703325253D2829207B20202F7573722F62696E2F67706B67207069703320222440220A7D005353485F415554485F534F434B3D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E2F2E7373682F6167656E742F732E3230524D6B6F466350352E737368642E333630383034322E63614837725067566563005445524D3D787465726D2D323536636F6C6F7200424153485F46554E435F706F6574727925253D2829207B20202F7573722F62696E2F67706B6720706F6574727920222440220A7D005348454C4C3D2F62696E2F6261736800434C4F554453444B5F494E5445524E414C5F555345523D7472756500434C4F554453444B5F434F4E544558545F41574152455F43455254494649434154455F434F4E4649475F46494C455F504154483D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004348524F4D455F52454D4F54455F4445534B544F505F44454641554C545F4445534B544F505F53495A45533D3136303078313230302C3338343078323136302C3338343078323536302C3531323078313434302C323136307833383430005844475F53455353494F4E5F545950453D74747900424153485F46554E435F706E707825253D2829207B20202F7573722F62696E2F67706B6720706E707820222440220A7D00424153485F46554E435F707974686F6E3325253D2829207B20202F7573722F62696E2F67706B6720707974686F6E3320222440220A7D00424153485F46554E435F70697025253D2829207B20202F7573722F62696E2F67706B672070697020222440220A7D00424153485F46554E435F7069707825253D2829207B20202F7573722F62696E2F67706B67207069707820222440220A7D004C414E473D656E5F55532E5554462D38005832305F484F4D453D2F676F6F676C652F646174612F72772F75736572732F68612F6861726A6F686E005353485F434F4E4E454354494F4E3D3137322E3235332E33312E323337203437383431203137322E32382E35372E313037203232005844475F52554E54494D455F4449523D2F72756E2F757365722F34393937333200424153485F46554E435F757625253D2829207B20202F7573722F62696E2F67706B6720757620222440220A7D00424153485F46554E435F707974686F6E25253D2829207B20202F7573722F62696E2F67706B6720707974686F6E20222440220A7D00474F4F474C455F4150495F43455254494649434154455F434F4E4649473D2F6574632F67636C6F75642F63657274696669636174655F636F6E6669672E6A736F6E004356535F5253483D73736800505954484F4E504154483D2F7573722F6C6F63616C2F6275696C64746F6F6C732F63757272656E742F73697465637573746F6D697A65005844475F53455353494F4E5F434C4153533D7573657200474F4F474C455F415554485F574542415554484E5F504C5547494E3D67636C6F7564776562617574686E00424153485F46554E435F70646D25253D2829207B20202F7573722F62696E2F67706B672070646D20222440220A7D0053545245414D5A5F534552564552533D5B323030313A343836303A663830323A3A37385D3A3935333000484F4D453D2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E005844475F444154415F444952533D2F7573722F73686172652F676E6F6D653A2F7573722F6C6F63616C2F73686172652F3A2F7573722F73686172652F002F746D702F612E6F7574000000000000000000 + - Type: Memory64List + Memory Ranges: + - Start of Memory Range: 0x555555557000 + Content: 01000200000000000000000000001440000000000000144000000000000039400000000000003E406672616D655F617265613A2025660A00011B033B3400000005000000E8EFFFFF8000000008F0FFFFA800000018F0FFFF5000000008F1FFFFC000000048F1FFFFE0000000000000001400000000000000017A5200017810011B0C070890010710140000001C000000C0EFFFFF2200000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000060EFFFFF20000000000E10460E184A0F0B770880003F1A3B2A33242200000000140000004400000058EFFFFF0800000000000000000000001C0000005C00000040F0FFFF3700000000410E108602430D06720C07080000001C0000007C00000060F0FFFF6100000000410E108602430D06025C0C0708000000000000040000001000000001000000474E55000000000003000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003051555555550000F050555555550000010000000000000029000000000000000C0000000000000000100000000000000D00000000000000E4110000000000001900000000000000D03D0000000000001B0000000000000008000000000000001A00000000000000D83D0000000000001C000000000000000800000000000000F5FEFF6F00000000B043555555550000050000000000000080445555555500000600000000000000D8435555555500000A000000000000008F000000000000000B000000000000001800000000000000150000000000000078DBFFF7FF7F00000300000000000000E87F555555550000020000000000000018000000000000001400000000000000070000000000000017000000000000001046555555550000070000000000000050455555555500000800000000000000C00000000000000009000000000000001800000000000000FBFFFF6F000000000000000800000000FEFFFF6F000000002005000000000000FFFFFF6F000000000100000000000000F0FFFF6F000000001045555555550000F9FFFF6F0000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E0ACDDF7FF7F0000000000000000000000000000000000000000000000000000F02BDFF7FF7F0000E03D00000000000010E3FFF7FF7F00001096FDF7FF7F0000 + - Start of Memory Range: 0x7FFFF7DAE000 + Content: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C093F9F7FF7F00004007FAF7FF7F00000000000000000000E0F9F3F7FF7F0000E0FFF3F7FF7F0000E008F4F7FF7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040E7DAF7FF7F0000E0F0DAF7FF7F000040E7DAF7FF7F000000000000000000000000000000000000007B97470D7B2415EB04A950654C280100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010DBFFF7FF7F000010DBFFF7FF7F0000A72D37000000000020EADAF7FF7F000020EADAF7FF7F0000E0FFFFFFFFFFFFFF0000000000000000000000000000000010D5FFFFFF7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050EADAF7FF7F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F0D5FFFFFF7F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E0DAF7FF7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000000000000000000000000000001000000000000000000000000000000B8E6DAF7FF7F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010DBF7FF7F0000786EFAF7FF7F000060D1FBF7FF7F0000E040F6F7FF7F00000050FCF7FF7F00001768FCF7FF7F0000F0E8FFF7FF7F00008457FCF7FF7F00000070FCF7FF7F000010E3FFF7FF7F0000A0DDFFF7FF7F00005864FFF7FF7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ... diff --git a/lldb/unittests/DAP/Inputs/linux-x86_64.out.yaml b/lldb/unittests/DAP/Inputs/linux-x86_64.out.yaml index b374c57693a4b..bf8a046337715 100644 --- a/lldb/unittests/DAP/Inputs/linux-x86_64.out.yaml +++ b/lldb/unittests/DAP/Inputs/linux-x86_64.out.yaml @@ -1,148 +1,618 @@ +# $ cat sample.c +# #include +# +# struct rect { +# double x, y, height, width; +# }; +# +# double frame_area(struct rect *rect) { +# if (!rect) return 0; +# return rect->height * rect->width; +# } +# +# int main(int argc, char**argv) { +# struct rect frame = {5, 5, 25, 30}; +# printf("frame_area: %f\n", frame_area(&frame)); +# return 0; +# } --- !ELF FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB - Type: ET_EXEC + Type: ET_DYN Machine: EM_X86_64 - Entry: 0x400144 + Entry: 0x1050 ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_R ] + VAddr: 0x40 + Align: 0x8 + Offset: 0x40 + - Type: PT_INTERP + Flags: [ PF_R ] + FirstSec: .interp + LastSec: .interp + VAddr: 0x394 + Offset: 0x394 - Type: PT_LOAD - Flags: [ PF_X, PF_R ] - FirstSec: .note.gnu.build-id - LastSec: .eh_frame - VAddr: 0x400000 - Align: 0x200000 + Flags: [ PF_R ] + FirstSec: .note.gnu.property + LastSec: .rela.plt + Align: 0x1000 Offset: 0x0 + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .init + LastSec: .fini + VAddr: 0x1000 + Align: 0x1000 + Offset: 0x1000 + - Type: PT_LOAD + Flags: [ PF_R ] + FirstSec: .rodata + LastSec: .note.ABI-tag + VAddr: 0x2000 + Align: 0x1000 + Offset: 0x2000 + - Type: PT_LOAD + Flags: [ PF_W, PF_R ] + FirstSec: .init_array + LastSec: .bss + VAddr: 0x3DD0 + Align: 0x1000 + Offset: 0x2DD0 + - Type: PT_DYNAMIC + Flags: [ PF_W, PF_R ] + FirstSec: .dynamic + LastSec: .dynamic + VAddr: 0x3DE0 + Align: 0x8 + Offset: 0x2DE0 + - Type: PT_NOTE + Flags: [ PF_R ] + FirstSec: .note.gnu.property + LastSec: .note.gnu.property + VAddr: 0x350 + Align: 0x8 + Offset: 0x350 - Type: PT_NOTE Flags: [ PF_R ] FirstSec: .note.gnu.build-id LastSec: .note.gnu.build-id - VAddr: 0x4000E8 + VAddr: 0x370 + Align: 0x4 + Offset: 0x370 + - Type: PT_NOTE + Flags: [ PF_R ] + FirstSec: .note.ABI-tag + LastSec: .note.ABI-tag + VAddr: 0x213C Align: 0x4 - Offset: 0xE8 + Offset: 0x213C + - Type: PT_GNU_PROPERTY + Flags: [ PF_R ] + FirstSec: .note.gnu.property + LastSec: .note.gnu.property + VAddr: 0x350 + Align: 0x8 + Offset: 0x350 + - Type: PT_GNU_EH_FRAME + Flags: [ PF_R ] + FirstSec: .eh_frame_hdr + LastSec: .eh_frame_hdr + VAddr: 0x2038 + Align: 0x4 + Offset: 0x2038 - Type: PT_GNU_STACK Flags: [ PF_W, PF_R ] Align: 0x10 Offset: 0x0 + - Type: PT_GNU_RELRO + Flags: [ PF_R ] + FirstSec: .init_array + LastSec: .got + VAddr: 0x3DD0 + Offset: 0x2DD0 Sections: + - Name: .note.gnu.property + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x350 + AddressAlign: 0x8 + Notes: + - Name: GNU + Desc: 028000C0040000000100000000000000 + Type: NT_GNU_PROPERTY_TYPE_0 - Name: .note.gnu.build-id Type: SHT_NOTE Flags: [ SHF_ALLOC ] - Address: 0x4000E8 + Address: 0x370 AddressAlign: 0x4 Notes: - Name: GNU - Desc: 01DF54A6045E657D3F8FFB9CE111878914F8BD6D + Desc: 768D260BD4FC15E892AAC361C910DF78AC15E194 Type: NT_PRPSINFO + - Name: .interp + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x394 + AddressAlign: 0x1 + Content: 2F6C696236342F6C642D6C696E75782D7838362D36342E736F2E3200 + - Name: .gnu.hash + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Address: 0x3B0 + Link: .dynsym + AddressAlign: 0x8 + Header: + SymNdx: 0x6 + Shift2: 0x6 + BloomFilter: [ 0x810000 ] + HashBuckets: [ 0x6, 0x0 ] + HashValues: [ 0x6DCE65D1 ] + - Name: .dynsym + Type: SHT_DYNSYM + Flags: [ SHF_ALLOC ] + Address: 0x3D8 + Link: .dynstr + AddressAlign: 0x8 + - Name: .dynstr + Type: SHT_STRTAB + Flags: [ SHF_ALLOC ] + Address: 0x480 + AddressAlign: 0x1 + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x510 + Link: .dynsym + AddressAlign: 0x2 + Entries: [ 0, 2, 1, 3, 1, 1, 3 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x520 + Link: .dynstr + AddressAlign: 0x8 + Dependencies: + - Version: 1 + File: libc.so.6 + Entries: + - Name: GLIBC_2.2.5 + Hash: 157882997 + Flags: 0 + Other: 3 + - Name: GLIBC_2.34 + Hash: 110530996 + Flags: 0 + Other: 2 + - Name: .rela.dyn + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Address: 0x550 + Link: .dynsym + AddressAlign: 0x8 + Relocations: + - Offset: 0x3DD0 + Type: R_X86_64_RELATIVE + Addend: 4400 + - Offset: 0x3DD8 + Type: R_X86_64_RELATIVE + Addend: 4336 + - Offset: 0x4010 + Type: R_X86_64_RELATIVE + Addend: 16400 + - Offset: 0x3FC0 + Symbol: __libc_start_main + Type: R_X86_64_GLOB_DAT + - Offset: 0x3FC8 + Symbol: _ITM_deregisterTMCloneTable + Type: R_X86_64_GLOB_DAT + - Offset: 0x3FD0 + Symbol: __gmon_start__ + Type: R_X86_64_GLOB_DAT + - Offset: 0x3FD8 + Symbol: _ITM_registerTMCloneTable + Type: R_X86_64_GLOB_DAT + - Offset: 0x3FE0 + Symbol: __cxa_finalize + Type: R_X86_64_GLOB_DAT + - Name: .rela.plt + Type: SHT_RELA + Flags: [ SHF_ALLOC, SHF_INFO_LINK ] + Address: 0x610 + Link: .dynsym + AddressAlign: 0x8 + Info: .got.plt + Relocations: + - Offset: 0x4000 + Symbol: printf + Type: R_X86_64_JUMP_SLOT + - Name: .init + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + AddressAlign: 0x4 + Offset: 0x1000 + Content: 4883EC08488B05C52F00004885C07402FFD04883C408C3 + - Name: .plt + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1020 + AddressAlign: 0x10 + EntSize: 0x10 + Content: FF35CA2F0000FF25CC2F00000F1F4000FF25CA2F00006800000000E9E0FFFFFF + - Name: .plt.got + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1040 + AddressAlign: 0x8 + EntSize: 0x8 + Content: FF259A2F00006690 - Name: .text Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Address: 0x40010C - AddressAlign: 0x1 - Content: 554889E548897DE8C645FF62488B45E8C6002F5DC3554889E54883EC2048897DE8488975E0C645FF66488B55E8488B45E04889D7FFD0C9C3554889E54883EC10C645FF5FBE0C014000BF00000000E8C2FFFFFFC9C3 + Address: 0x1050 + AddressAlign: 0x10 + Content: 31ED4989D15E4889E24883E4F050544531C031C9488D3D15010000FF154F2F0000F4662E0F1F8400000000000F1F4000488D3D912F0000488D058A2F00004839F87415488B052E2F00004885C07409FFE00F1F8000000000C30F1F8000000000488D3D612F0000488D355A2F00004829FE4889F048C1EE3F48C1F8034801C648D1FE7414488B05FD2E00004885C07408FFE0660F1F440000C30F1F8000000000F30F1EFA803D1D2F000000752B5548833DDA2E0000004889E5740C488B3DFE2E0000E829FFFFFFE864FFFFFFC605F52E0000015DC30F1F00C30F1F8000000000F30F1EFAE977FFFFFF0F1F8000000000554889E548897DF048837DF000750A0F57C0F20F1145F8EB17488B45F0F20F104010488B45F0F20F594018F20F1145F8F20F1045F85DC3660F1F840000000000554889E54883EC30C745FC00000000897DF8488975F0488B056B0E0000488945D0488B05680E0000488945D8488B05650E0000488945E0488B05620E0000488945E8488D7DD0E875FFFFFF488D3D560E0000B001E857FEFFFF31C04883C4305DC3 + - Name: .fini + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x11E4 + AddressAlign: 0x4 + Content: 4883EC084883C408C3 + - Name: .rodata + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2000 + AddressAlign: 0x8 + Offset: 0x2000 + Content: 01000200000000000000000000001440000000000000144000000000000039400000000000003E406672616D655F617265613A2025660A00 + - Name: .eh_frame_hdr + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x2038 + AddressAlign: 0x4 + Content: 011B033B3400000005000000E8EFFFFF8000000008F0FFFFA800000018F0FFFF5000000008F1FFFFC000000048F1FFFFE0000000 - Name: .eh_frame Type: SHT_PROGBITS Flags: [ SHF_ALLOC ] - Address: 0x400168 + Address: 0x2070 + AddressAlign: 0x8 + Content: 1400000000000000017A5200017810011B0C070890010710140000001C000000C0EFFFFF2200000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000060EFFFFF20000000000E10460E184A0F0B770880003F1A3B2A33242200000000140000004400000058EFFFFF0800000000000000000000001C0000005C00000040F0FFFF3700000000410E108602430D06720C07080000001C0000007C00000060F0FFFF6100000000410E108602430D06025C0C0708000000000000 + - Name: .note.ABI-tag + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x213C + AddressAlign: 0x4 + Notes: + - Name: GNU + Desc: '00000000030000000200000000000000' + Type: NT_VERSION + - Name: .init_array + Type: SHT_INIT_ARRAY + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x3DD0 + AddressAlign: 0x8 + EntSize: 0x8 + Offset: 0x2DD0 + Content: '3011000000000000' + - Name: .fini_array + Type: SHT_FINI_ARRAY + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x3DD8 AddressAlign: 0x8 - Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C00000084FFFFFF1500000000410E108602430D06500C07080000001C0000003C00000079FFFFFF2300000000410E108602430D065E0C07080000001C0000005C0000007CFFFFFF1D00000000410E108602430D06580C0708000000 + EntSize: 0x8 + Content: F010000000000000 + - Name: .dynamic + Type: SHT_DYNAMIC + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x3DE0 + Link: .dynstr + AddressAlign: 0x8 + Entries: + - Tag: DT_NEEDED + Value: 0x29 + - Tag: DT_INIT + Value: 0x1000 + - Tag: DT_FINI + Value: 0x11E4 + - Tag: DT_INIT_ARRAY + Value: 0x3DD0 + - Tag: DT_INIT_ARRAYSZ + Value: 0x8 + - Tag: DT_FINI_ARRAY + Value: 0x3DD8 + - Tag: DT_FINI_ARRAYSZ + Value: 0x8 + - Tag: DT_GNU_HASH + Value: 0x3B0 + - Tag: DT_STRTAB + Value: 0x480 + - Tag: DT_SYMTAB + Value: 0x3D8 + - Tag: DT_STRSZ + Value: 0x8F + - Tag: DT_SYMENT + Value: 0x18 + - Tag: DT_DEBUG + Value: 0x0 + - Tag: DT_PLTGOT + Value: 0x3FE8 + - Tag: DT_PLTRELSZ + Value: 0x18 + - Tag: DT_PLTREL + Value: 0x7 + - Tag: DT_JMPREL + Value: 0x610 + - Tag: DT_RELA + Value: 0x550 + - Tag: DT_RELASZ + Value: 0xC0 + - Tag: DT_RELAENT + Value: 0x18 + - Tag: DT_FLAGS_1 + Value: 0x8000000 + - Tag: DT_VERNEED + Value: 0x520 + - Tag: DT_VERNEEDNUM + Value: 0x1 + - Tag: DT_VERSYM + Value: 0x510 + - Tag: DT_RELACOUNT + Value: 0x3 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Name: .got + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x3FC0 + AddressAlign: 0x8 + EntSize: 0x8 + Content: '00000000000000000000000000000000000000000000000000000000000000000000000000000000' + - Name: .got.plt + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x3FE8 + AddressAlign: 0x8 + EntSize: 0x8 + Content: E03D000000000000000000000000000000000000000000003610000000000000 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x4008 + AddressAlign: 0x8 + Content: '00000000000000001040000000000000' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x4018 + AddressAlign: 0x1 + Size: 0x8 - Name: .comment Type: SHT_PROGBITS Flags: [ SHF_MERGE, SHF_STRINGS ] AddressAlign: 0x1 EntSize: 0x1 - Content: 4743433A20285562756E747520342E382E342D327562756E7475317E31342E30342920342E382E3400 + Content: 4743433A202844656269616E2031352E322E302D34292031352E322E300044656269616E20636C616E672076657273696F6E2031392E312E37202831302E312B6275696C64312900 - Name: .debug_info Type: SHT_PROGBITS AddressAlign: 0x1 - Content: EC00000004000000000008011300000001070000003F0000000C01400000000000550000000000000000000000026261720001010C014000000000001500000000000000019C65000000030E00000001016500000002915804460001036B00000002916F0005086B0000000601065800000007666F6F00010721014000000000002300000000000000019CB8000000030E00000001076500000002915803000000000107C300000002915004460001096B00000002916F0008C30000000965000000000508B80000000A51000000010D44014000000000001D00000000000000019C044600010F6B00000002916F0000 + Content: CB000000050001080000000001001D000108000000000000000201A100000008000000022D000000000E02A1000339000000043D0000001000050306010604080707013700000001560500078D000000080291700900079500000000070261000000015607000C91000000080291780E000C91000000080291700F000CC40000000902915010000D9A0000000005060408050805040A9A0000000B092000030C0A8D0000000004000C0B8D0000000004080C0C8D0000000004100C0D8D000000000418000AC90000000A3900000000 - Name: .debug_abbrev Type: SHT_PROGBITS AddressAlign: 0x1 - Content: 011101250E130B030E1B0E1101120710170000022E0103083A0B3B0B271911011207401897421901130000030500030E3A0B3B0B49130218000004340003083A0B3B0B491302180000050F000B0B491300000624000B0B3E0B030E0000072E0103083A0B3B0B271911011207401896421901130000081501271901130000090500491300000A2E013F19030E3A0B3B0B2719110112074018964219000000 + Content: 011101252513050325721710171B25111B12067317000002340049133A0B3B0B02180000030101491300000421004913370B000005240003253E0B0B0B000006240003250B0B3E0B0000072E01111B1206401803253A0B3B0B271949133F190000080500021803253A0B3B0B49130000093400021803253A0B3B0B491300000A0F00491300000B130103250B0B3A0B3B0B00000C0D00032549133A0B3B0B380B000000 - Name: .debug_line Type: SHT_PROGBITS AddressAlign: 0x1 - Content: 3F00000002001D0000000101FB0E0D000101010100000001000001006D61696E2E6300000000000009020C0140000000000013834B7531F34BC931834BE50202000101 + Content: 8C0000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E011F00000000D56EC241486226563655292B9539311D040000090240110000000000001805080A8305070658050E2E050A069F0510064A05195805174A05035805010659060B58050006AE050F0A0859051E022C130503069006D7060B2E0206000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 2F7573722F6C6F63616C2F676F6F676C652F686F6D652F6861726A6F686E002F746D702F73616D706C652E6300 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 4800000005000000000000002A00000038000000570000005C000000700000007B00000082000000870000008B0000009000000092000000940000009B000000A1000000A6000000AB000000 Symbols: - - Name: .note.gnu.build-id - Type: STT_SECTION - Section: .note.gnu.build-id - Value: 0x4000E8 - - Name: .text - Type: STT_SECTION - Section: .text - Value: 0x40010C - - Name: .eh_frame - Type: STT_SECTION - Section: .eh_frame - Value: 0x400168 - - Name: .comment - Type: STT_SECTION - Section: .comment - - Name: .debug_aranges - Type: STT_SECTION - Section: .debug_aranges - - Name: .debug_info - Type: STT_SECTION - Section: .debug_info - - Name: .debug_abbrev - Type: STT_SECTION - Section: .debug_abbrev - - Name: .debug_line - Type: STT_SECTION - Section: .debug_line - - Name: .debug_str - Type: STT_SECTION - Section: .debug_str - - Name: main.c + - Name: Scrt1.o + Type: STT_FILE + Index: SHN_ABS + - Name: __abi_tag + Type: STT_OBJECT + Section: .note.ABI-tag + Value: 0x213C + Size: 0x20 + - Name: crtstuff.c Type: STT_FILE Index: SHN_ABS - - Name: bar + - Name: deregister_tm_clones Type: STT_FUNC Section: .text - Value: 0x40010C - Size: 0x15 - - Name: foo + Value: 0x1080 + - Name: register_tm_clones Type: STT_FUNC Section: .text - Value: 0x400121 - Size: 0x23 + Value: 0x10B0 + - Name: __do_global_dtors_aux + Type: STT_FUNC + Section: .text + Value: 0x10F0 + - Name: completed.0 + Type: STT_OBJECT + Section: .bss + Value: 0x4018 + Size: 0x1 + - Name: __do_global_dtors_aux_fini_array_entry + Type: STT_OBJECT + Section: .fini_array + Value: 0x3DD8 + - Name: frame_dummy + Type: STT_FUNC + Section: .text + Value: 0x1130 + - Name: __frame_dummy_init_array_entry + Type: STT_OBJECT + Section: .init_array + Value: 0x3DD0 + - Name: sample.c + Type: STT_FILE + Index: SHN_ABS + - Name: 'crtstuff.c (1)' + Type: STT_FILE + Index: SHN_ABS + - Name: __FRAME_END__ + Type: STT_OBJECT + Section: .eh_frame + Value: 0x2138 - Type: STT_FILE Index: SHN_ABS + - Name: _DYNAMIC + Type: STT_OBJECT + Section: .dynamic + Value: 0x3DE0 + - Name: __GNU_EH_FRAME_HDR + Section: .eh_frame_hdr + Value: 0x2038 + - Name: _GLOBAL_OFFSET_TABLE_ + Type: STT_OBJECT + Section: .got.plt + Value: 0x3FE8 + - Name: '__libc_start_main@GLIBC_2.34' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _ITM_deregisterTMCloneTable + Binding: STB_WEAK + - Name: data_start + Section: .data + Binding: STB_WEAK + Value: 0x4008 + - Name: _edata + Section: .data + Binding: STB_GLOBAL + Value: 0x4018 + - Name: _fini + Type: STT_FUNC + Section: .fini + Binding: STB_GLOBAL + Value: 0x11E4 + Other: [ STV_HIDDEN ] + - Name: 'printf@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: __data_start + Section: .data + Binding: STB_GLOBAL + Value: 0x4008 + - Name: __gmon_start__ + Binding: STB_WEAK + - Name: __dso_handle + Type: STT_OBJECT + Section: .data + Binding: STB_GLOBAL + Value: 0x4010 + Other: [ STV_HIDDEN ] + - Name: _IO_stdin_used + Type: STT_OBJECT + Section: .rodata + Binding: STB_GLOBAL + Value: 0x2000 + Size: 0x4 + - Name: _end + Section: .bss + Binding: STB_GLOBAL + Value: 0x4020 - Name: _start Type: STT_FUNC Section: .text Binding: STB_GLOBAL - Value: 0x400144 - Size: 0x1D + Value: 0x1050 + Size: 0x22 + - Name: frame_area + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x1140 + Size: 0x37 - Name: __bss_start - Section: .eh_frame + Section: .bss Binding: STB_GLOBAL - Value: 0x601000 - - Name: _edata - Section: .eh_frame + Value: 0x4018 + - Name: main + Type: STT_FUNC + Section: .text Binding: STB_GLOBAL - Value: 0x601000 - - Name: _end - Section: .eh_frame + Value: 0x1180 + Size: 0x61 + - Name: __TMC_END__ + Type: STT_OBJECT + Section: .data Binding: STB_GLOBAL - Value: 0x601000 + Value: 0x4018 + Other: [ STV_HIDDEN ] + - Name: _ITM_registerTMCloneTable + Binding: STB_WEAK + - Name: '__cxa_finalize@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_WEAK + - Name: _init + Type: STT_FUNC + Section: .init + Binding: STB_GLOBAL + Value: 0x1000 + Other: [ STV_HIDDEN ] +DynamicSymbols: + - Name: __libc_start_main + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _ITM_deregisterTMCloneTable + Binding: STB_WEAK + - Name: printf + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: __gmon_start__ + Binding: STB_WEAK + - Name: _ITM_registerTMCloneTable + Binding: STB_WEAK + - Name: __cxa_finalize + Type: STT_FUNC + Binding: STB_WEAK DWARF: debug_str: - - boomer - - main.c - - boom - - 'GNU C 4.8.4 -mtune=generic -march=x86-64 -g' - - '/home/labath/test' - - _start + - 'Debian clang version 19.1.7 (10.1+build1)' + - '/tmp/sample.c' + - '/usr/local/google/home/harjohn' - char - debug_aranges: - - Length: 0x2C - Version: 2 - CuOffset: 0x0 + - __ARRAY_SIZE_TYPE__ + - frame_area + - double + - main + - int + - rect + - x + - y + - height + - width + - argc + - argv + - frame + debug_addr: + - Length: 0x1C + Version: 0x5 AddressSize: 0x8 - Descriptors: - - Address: 0x40010C - Length: 0x55 + Entries: + - Address: 0x2028 + - Address: 0x1140 + - Address: 0x1180 ... diff --git a/lldb/unittests/DAP/VariablesTest.cpp b/lldb/unittests/DAP/VariablesTest.cpp index 8a1c9ce2c502f..fdfd2ae3151b6 100644 --- a/lldb/unittests/DAP/VariablesTest.cpp +++ b/lldb/unittests/DAP/VariablesTest.cpp @@ -10,10 +10,17 @@ #include "DAPLog.h" #include "Protocol/DAPTypes.h" #include "Protocol/ProtocolTypes.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBFrame.h" +#include "lldb/API/SBThread.h" #include "lldb/API/SBValue.h" +#include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" +#include +using namespace llvm; +using namespace lldb; using namespace lldb_dap; using namespace lldb_dap::protocol; @@ -22,11 +29,62 @@ class VariablesTest : public ::testing::Test { public: VariablesTest() : log(llvm::nulls(), mutex), vars(log) {} + static void SetUpTestSuite() { + lldb::SBError error = SBDebugger::InitializeWithErrorHandling(); + EXPECT_TRUE(error.Success()); + } + static void TeatUpTestSuite() { SBDebugger::Terminate(); } + + void TearDown() override { + if (core) + ASSERT_THAT_ERROR(core->discard(), Succeeded()); + if (binary) + ASSERT_THAT_ERROR(binary->discard(), Succeeded()); + if (debugger) + debugger.Clear(); + } + protected: enum : bool { Permanent = true, Temporary = false }; Log::Mutex mutex; Log log; VariableReferenceStorage vars; + lldb::SBDebugger debugger; + lldb::SBTarget target; + lldb::SBProcess process; + + static constexpr llvm::StringLiteral k_binary = "linux-x86_64.out.yaml"; + static constexpr llvm::StringLiteral k_core = "linux-x86_64.core.yaml"; + + std::optional core; + std::optional binary; + + void CreateDebugger() { debugger = lldb::SBDebugger::Create(); } + + void LoadCore() { + ASSERT_TRUE(debugger); + + llvm::Expected binary_yaml = + lldb_private::TestFile::fromYamlFile(k_binary); + ASSERT_THAT_EXPECTED(binary_yaml, Succeeded()); + llvm::Expected binary_file = + binary_yaml->writeToTemporaryFile(); + ASSERT_THAT_EXPECTED(binary_file, Succeeded()); + binary = std::move(*binary_file); + target = debugger.CreateTarget(binary->TmpName.data()); + ASSERT_TRUE(target); + debugger.SetSelectedTarget(target); + + llvm::Expected core_yaml = + lldb_private::TestFile::fromYamlFile(k_core); + ASSERT_THAT_EXPECTED(core_yaml, Succeeded()); + llvm::Expected core_file = + core_yaml->writeToTemporaryFile(); + ASSERT_THAT_EXPECTED(core_file, Succeeded()); + this->core = std::move(*core_file); + process = target.LoadCore(this->core->TmpName.data()); + ASSERT_TRUE(process); + } static const protocol::Scope * FindScope(const std::vector &scopes, @@ -40,10 +98,16 @@ class VariablesTest : public ::testing::Test { }; TEST_F(VariablesTest, GetNewVariableReference_UniqueAndRanges) { - const var_ref_t temp1 = vars.InsertVariable(lldb::SBValue(), Temporary); - const var_ref_t temp2 = vars.InsertVariable(lldb::SBValue(), Temporary); - const var_ref_t perm1 = vars.InsertVariable(lldb::SBValue(), Permanent); - const var_ref_t perm2 = vars.InsertVariable(lldb::SBValue(), Permanent); + CreateDebugger(); + LoadCore(); + auto x15 = target.CreateValueFromExpression("x", "15"); + auto y42 = target.CreateValueFromExpression("y", "42"); + auto gzero = target.CreateValueFromExpression("$0", "42"); + auto gone = target.CreateValueFromExpression("$1", "7"); + const var_ref_t temp1 = vars.Insert(x15, Temporary); + const var_ref_t temp2 = vars.Insert(y42, Temporary); + const var_ref_t perm1 = vars.Insert(gzero, Permanent); + const var_ref_t perm2 = vars.Insert(gone, Permanent); EXPECT_NE(temp1.AsUInt32(), temp2.AsUInt32()); EXPECT_NE(perm1.AsUInt32(), perm2.AsUInt32()); EXPECT_LT(temp1.AsUInt32(), perm1.AsUInt32()); @@ -52,7 +116,7 @@ TEST_F(VariablesTest, GetNewVariableReference_UniqueAndRanges) { TEST_F(VariablesTest, InsertAndGetVariable_Temporary) { lldb::SBValue dummy; - const var_ref_t ref = vars.InsertVariable(dummy, Temporary); + const var_ref_t ref = vars.Insert(dummy, Temporary); lldb::SBValue out = vars.GetVariable(ref); EXPECT_EQ(out.IsValid(), dummy.IsValid()); @@ -60,15 +124,15 @@ TEST_F(VariablesTest, InsertAndGetVariable_Temporary) { TEST_F(VariablesTest, InsertAndGetVariable_Permanent) { lldb::SBValue dummy; - const var_ref_t ref = vars.InsertVariable(dummy, Permanent); + const var_ref_t ref = vars.Insert(dummy, Permanent); lldb::SBValue out = vars.GetVariable(ref); EXPECT_EQ(out.IsValid(), dummy.IsValid()); } TEST_F(VariablesTest, IsPermanentVariableReference) { - const var_ref_t perm = vars.InsertVariable(lldb::SBValue(), Permanent); - const var_ref_t temp = vars.InsertVariable(lldb::SBValue(), Temporary); + const var_ref_t perm = vars.Insert(lldb::SBValue(), Permanent); + const var_ref_t temp = vars.Insert(lldb::SBValue(), Temporary); EXPECT_EQ(perm.Kind(), eReferenceKindPermanent); EXPECT_EQ(temp.Kind(), eReferenceKindTemporary); @@ -76,8 +140,8 @@ TEST_F(VariablesTest, IsPermanentVariableReference) { TEST_F(VariablesTest, Clear_RemovesTemporaryKeepsPermanent) { lldb::SBValue dummy; - const var_ref_t temp = vars.InsertVariable(dummy, Temporary); - const var_ref_t perm = vars.InsertVariable(dummy, Permanent); + const var_ref_t temp = vars.Insert(dummy, Temporary); + const var_ref_t perm = vars.Insert(dummy, Permanent); vars.Clear(); EXPECT_FALSE(vars.GetVariable(temp).IsValid()); @@ -85,9 +149,11 @@ TEST_F(VariablesTest, Clear_RemovesTemporaryKeepsPermanent) { } TEST_F(VariablesTest, VariablesStore) { - lldb::SBFrame frame; + CreateDebugger(); + LoadCore(); + lldb::SBFrame frame = process.GetSelectedThread().GetSelectedFrame(); - std::vector scopes = vars.CreateScopes(frame); + std::vector scopes = vars.Insert(frame); const protocol::Scope *locals_scope = FindScope(scopes, "Locals"); const protocol::Scope *globals_scope = FindScope(scopes, "Globals"); @@ -110,17 +176,43 @@ TEST_F(VariablesTest, VariablesStore) { const var_ref_t local_ref = locals_scope->variablesReference; const var_ref_t global_ref = globals_scope->variablesReference; const var_ref_t register_ref = registers_scope->variablesReference; - ASSERT_EQ(global_ref.Kind(), eReferenceKindScope); - ASSERT_EQ(local_ref.Kind(), eReferenceKindScope); - ASSERT_EQ(register_ref.Kind(), eReferenceKindScope); + ASSERT_EQ(global_ref.Kind(), eReferenceKindTemporary); + ASSERT_EQ(local_ref.Kind(), eReferenceKindTemporary); + ASSERT_EQ(register_ref.Kind(), eReferenceKindTemporary); EXPECT_EQ(vars.GetVariableStore(var_ref_t(9999)), nullptr); + + ASSERT_TRUE(vars.FindVariable(local_ref, "rect").IsValid()); + + auto variables = locals_store->GetVariables(vars, {}, {}); + ASSERT_THAT_EXPECTED(variables, Succeeded()); + ASSERT_EQ(variables->size(), 1u); + auto rect = variables->at(0); + ASSERT_EQ(rect.name, "rect"); + + VariablesArguments args; + args.variablesReference = rect.variablesReference; + + auto *store = vars.GetVariableStore(args.variablesReference); + ASSERT_NE(store, nullptr); + + variables = store->GetVariables(vars, {}, args); + ASSERT_THAT_EXPECTED(variables, Succeeded()); + ASSERT_EQ(variables->size(), 4u); + EXPECT_EQ(variables->at(0).name, "x"); + EXPECT_EQ(variables->at(0).value, "5"); + EXPECT_EQ(variables->at(1).name, "y"); + EXPECT_EQ(variables->at(1).value, "5"); + EXPECT_EQ(variables->at(2).name, "height"); + EXPECT_EQ(variables->at(2).value, "25"); + EXPECT_EQ(variables->at(3).name, "width"); + EXPECT_EQ(variables->at(3).value, "30"); } TEST_F(VariablesTest, FindVariable_LocalsByName) { lldb::SBFrame frame; - std::vector scopes = vars.CreateScopes(frame); + std::vector scopes = vars.Insert(frame); const protocol::Scope *locals_scope = FindScope(scopes, "Locals"); ASSERT_NE(locals_scope, nullptr); From 852c6ef5aca60c17c2b0972d44b4664759884927 Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Fri, 27 Feb 2026 10:50:25 -0800 Subject: [PATCH 26/58] [mlir][LLVM] Let decomposeValue/composeValue handle aggregates (#183405) This commit updates the LLVM::decomposeValue and LLVM::composeValue methods to handle aggregate types - LLVM arrays and structs, and to have different behaviors on dealing with types like pointers that can't be bitcast to fixed-size integers. This allows the "any type" on gpu.subgroup_broadcast to be more comprehensive - you can broadcast a memref to a subgroup by decomposing it, for example. (This branched off of getting an LLM to implement ValueuboundsOpInterface on subgroup_broadcast, having it add handling for the dimensions of shaped types, and realizing that there's no fundamental reason you can't broadcast a memref or the like) --------- Co-authored-by: Claude Opus 4.6 --- .../mlir/Conversion/LLVMCommon/Pattern.h | 14 +- .../AMDGPUToROCDL/AMDGPUToROCDL.cpp | 12 +- .../GPUToROCDL/LowerGpuOpsToROCDLOps.cpp | 14 +- mlir/lib/Conversion/LLVMCommon/Pattern.cpp | 168 ++++++++++++++---- .../Conversion/GPUToROCDL/gpu-to-rocdl.mlir | 69 +++++++ 5 files changed, 232 insertions(+), 45 deletions(-) diff --git a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h index cacd500d41291..562ce48e23f26 100644 --- a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h +++ b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h @@ -66,10 +66,16 @@ bool opHasUnsupportedFloatingPointTypes(Operation *op, } // namespace detail /// Decomposes a `src` value into a set of values of type `dstType` through -/// series of bitcasts and vector ops. Src and dst types are expected to be int -/// or float types or vector types of them. -SmallVector decomposeValue(OpBuilder &builder, Location loc, Value src, - Type dstType); +/// series of bitcasts and vector ops. Handles int, float, vector types as well +/// as LLVM aggregate types (LLVMArrayType, LLVMStructType) by recursively +/// extracting elements. +/// +/// When `permitVariablySizedScalars` is true, leaf types that have no fixed +/// bit width (e.g., `!llvm.ptr`) are passed through as-is (1 element in +/// result). When false (default), encountering such a type returns failure. +LogicalResult decomposeValue(OpBuilder &builder, Location loc, Value src, + Type dstType, SmallVectorImpl &result, + bool permitVariablySizedScalars = false); /// Composes a set of `src` values into a single value of type `dstType` through /// series of bitcasts and vector ops. Inversely to `decomposeValue`, this diff --git a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp index 3c2c61b2426e9..379d6180596e9 100644 --- a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp +++ b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp @@ -2530,8 +2530,10 @@ struct AMDGPUSwizzleBitModeLowering Location loc = op.getLoc(); Type i32 = rewriter.getI32Type(); Value src = adaptor.getSrc(); - SmallVector decomposed = - LLVM::decomposeValue(rewriter, loc, src, i32); + SmallVector decomposed; + if (failed(LLVM::decomposeValue(rewriter, loc, src, i32, decomposed))) + return rewriter.notifyMatchFailure(op, + "failed to decompose value to i32"); unsigned andMask = op.getAndMask(); unsigned orMask = op.getOrMask(); unsigned xorMask = op.getXorMask(); @@ -2573,8 +2575,10 @@ struct AMDGPUPermlaneLowering : public ConvertOpToLLVMPattern { bool fi = op.getFetchInactive(); bool boundctrl = op.getBoundCtrl(); - SmallVector decomposed = - LLVM::decomposeValue(rewriter, loc, src, i32); + SmallVector decomposed; + if (failed(LLVM::decomposeValue(rewriter, loc, src, i32, decomposed))) + return rewriter.notifyMatchFailure(op, + "failed to decompose value to i32"); SmallVector permuted; for (Value v : decomposed) { diff --git a/mlir/lib/Conversion/GPUToROCDL/LowerGpuOpsToROCDLOps.cpp b/mlir/lib/Conversion/GPUToROCDL/LowerGpuOpsToROCDLOps.cpp index 096554d53e031..65353fedc9c4f 100644 --- a/mlir/lib/Conversion/GPUToROCDL/LowerGpuOpsToROCDLOps.cpp +++ b/mlir/lib/Conversion/GPUToROCDL/LowerGpuOpsToROCDLOps.cpp @@ -271,8 +271,11 @@ struct GPUSubgroupBroadcastOpToROCDL Type i32 = rewriter.getI32Type(); Location loc = op.getLoc(); - SmallVector decomposed = - LLVM::decomposeValue(rewriter, loc, src, i32); + SmallVector decomposed; + if (failed(LLVM::decomposeValue(rewriter, loc, src, i32, decomposed, + /*permitVariablySizedScalars=*/true))) + return rewriter.notifyMatchFailure(op, + "Unexpected decomposition failure"); SmallVector results; results.reserve(decomposed.size()); @@ -359,8 +362,11 @@ struct GPUShuffleOpLowering : public ConvertOpToLLVMPattern { Value dwordAlignedDstLane = LLVM::ShlOp::create(rewriter, loc, int32Type, selectDstLane, two); - SmallVector decomposed = - LLVM::decomposeValue(rewriter, loc, initShflValue, int32Type); + SmallVector decomposed; + if (failed(LLVM::decomposeValue(rewriter, loc, initShflValue, int32Type, + decomposed))) + return rewriter.notifyMatchFailure(op, + "failed to decompose value to i32"); SmallVector swizzled; for (Value v : decomposed) { Value res = ROCDL::DsBpermuteOp::create(rewriter, loc, int32Type, diff --git a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp index 640ff3d7c3c7d..38f71b916b5b8 100644 --- a/mlir/lib/Conversion/LLVMCommon/Pattern.cpp +++ b/mlir/lib/Conversion/LLVMCommon/Pattern.cpp @@ -384,23 +384,68 @@ static unsigned getBitWidth(Type type) { return vec.getNumElements() * getBitWidth(vec.getElementType()); } +/// Returns true if every leaf in `type` (recursing through LLVM arrays and +/// structs) is either equal to `dstType` or has a fixed bit width. +static bool isFixedSizeAggregate(Type type, Type dstType) { + if (type == dstType) + return true; + if (auto arrayType = dyn_cast(type)) + return isFixedSizeAggregate(arrayType.getElementType(), dstType); + if (auto structType = dyn_cast(type)) + return llvm::all_of(structType.getBody(), [&](Type fieldType) { + return isFixedSizeAggregate(fieldType, dstType); + }); + if (auto vecTy = dyn_cast(type)) + return !vecTy.isScalable(); + return type.isIntOrFloat(); +} + static Value createI32Constant(OpBuilder &builder, Location loc, int32_t value) { Type i32 = builder.getI32Type(); return LLVM::ConstantOp::create(builder, loc, i32, value); } -SmallVector mlir::LLVM::decomposeValue(OpBuilder &builder, Location loc, - Value src, Type dstType) { +/// Recursive implementation of decomposeValue. When +/// `permitVariablySizedScalars` is false, callers must ensure +/// isFixedSizeAggregate() holds before calling this. +static void decomposeValueImpl(OpBuilder &builder, Location loc, Value src, + Type dstType, SmallVectorImpl &result) { Type srcType = src.getType(); - if (srcType == dstType) - return {src}; + if (srcType == dstType) { + result.push_back(src); + return; + } + + if (auto arrayType = dyn_cast(srcType)) { + for (auto i : llvm::seq(arrayType.getNumElements())) { + Value elem = LLVM::ExtractValueOp::create(builder, loc, src, i); + decomposeValueImpl(builder, loc, elem, dstType, result); + } + return; + } + + if (auto structType = dyn_cast(srcType)) { + for (auto [i, fieldType] : llvm::enumerate(structType.getBody())) { + Value field = LLVM::ExtractValueOp::create(builder, loc, src, + static_cast(i)); + decomposeValueImpl(builder, loc, field, dstType, result); + } + return; + } + + // Variably sized leaf types (e.g., ptr) — pass through as-is. + if (!srcType.isIntOrFloat() && !isa(srcType)) { + result.push_back(src); + return; + } unsigned srcBitWidth = getBitWidth(srcType); unsigned dstBitWidth = getBitWidth(dstType); if (srcBitWidth == dstBitWidth) { Value cast = LLVM::BitcastOp::create(builder, loc, dstType, src); - return {cast}; + result.push_back(cast); + return; } if (dstBitWidth > srcBitWidth) { @@ -410,7 +455,8 @@ SmallVector mlir::LLVM::decomposeValue(OpBuilder &builder, Location loc, auto largerInt = builder.getIntegerType(dstBitWidth); Value res = LLVM::ZExtOp::create(builder, loc, largerInt, src); - return {res}; + result.push_back(res); + return; } assert(srcBitWidth % dstBitWidth == 0 && "src bit width must be a multiple of dst bit width"); @@ -419,47 +465,94 @@ SmallVector mlir::LLVM::decomposeValue(OpBuilder &builder, Location loc, src = LLVM::BitcastOp::create(builder, loc, vecType, src); - SmallVector res; for (auto i : llvm::seq(numElements)) { Value idx = createI32Constant(builder, loc, i); Value elem = LLVM::ExtractElementOp::create(builder, loc, src, idx); - res.emplace_back(elem); + result.push_back(elem); } - - return res; } -Value mlir::LLVM::composeValue(OpBuilder &builder, Location loc, ValueRange src, - Type dstType) { - assert(!src.empty() && "src range must not be empty"); - if (src.size() == 1) { - Value res = src.front(); - if (res.getType() == dstType) - return res; +LogicalResult mlir::LLVM::decomposeValue(OpBuilder &builder, Location loc, + Value src, Type dstType, + SmallVectorImpl &result, + bool permitVariablySizedScalars) { + // Check the type tree before emitting any IR, so that a failing pattern + // leaves the IR unmodified. + if (!permitVariablySizedScalars && + !isFixedSizeAggregate(src.getType(), dstType)) + return failure(); - unsigned srcBitWidth = getBitWidth(res.getType()); - unsigned dstBitWidth = getBitWidth(dstType); - if (dstBitWidth < srcBitWidth) { - auto largerInt = builder.getIntegerType(srcBitWidth); - if (res.getType() != largerInt) - res = LLVM::BitcastOp::create(builder, loc, largerInt, res); + decomposeValueImpl(builder, loc, src, dstType, result); + return success(); +} + +/// Recursive implementation of composeValue. Consumes elements from `src` +/// starting at `offset`, advancing it past the consumed elements. +static Value composeValueImpl(OpBuilder &builder, Location loc, ValueRange src, + size_t &offset, Type dstType) { + if (auto arrayType = dyn_cast(dstType)) { + Value result = LLVM::PoisonOp::create(builder, loc, arrayType); + Type elemType = arrayType.getElementType(); + for (auto i : llvm::seq(arrayType.getNumElements())) { + Value elem = composeValueImpl(builder, loc, src, offset, elemType); + result = LLVM::InsertValueOp::create(builder, loc, result, elem, i); + } + return result; + } - auto smallerInt = builder.getIntegerType(dstBitWidth); - res = LLVM::TruncOp::create(builder, loc, smallerInt, res); + if (auto structType = dyn_cast(dstType)) { + Value result = LLVM::PoisonOp::create(builder, loc, structType); + for (auto [i, fieldType] : llvm::enumerate(structType.getBody())) { + Value field = composeValueImpl(builder, loc, src, offset, fieldType); + result = LLVM::InsertValueOp::create(builder, loc, result, field, + static_cast(i)); } + return result; + } + + // Variably sized leaf types (e.g., ptr) — consume and return as-is. + if (!dstType.isIntOrFloat() && !isa(dstType)) + return src[offset++]; + + unsigned dstBitWidth = getBitWidth(dstType); - if (res.getType() != dstType) - res = LLVM::BitcastOp::create(builder, loc, dstType, res); + Value front = src[offset]; + if (front.getType() == dstType) { + ++offset; + return front; + } - return res; + // Single element wider than or equal to dst: bitcast/trunc. + if (front.getType().isIntOrFloat() || isa(front.getType())) { + unsigned srcBitWidth = getBitWidth(front.getType()); + if (srcBitWidth >= dstBitWidth) { + ++offset; + Value res = front; + if (dstBitWidth < srcBitWidth) { + auto largerInt = builder.getIntegerType(srcBitWidth); + if (res.getType() != largerInt) + res = LLVM::BitcastOp::create(builder, loc, largerInt, res); + + auto smallerInt = builder.getIntegerType(dstBitWidth); + res = LLVM::TruncOp::create(builder, loc, smallerInt, res); + } + if (res.getType() != dstType) + res = LLVM::BitcastOp::create(builder, loc, dstType, res); + return res; + } } - int64_t numElements = src.size(); - auto srcType = VectorType::get(numElements, src.front().getType()); - Value res = LLVM::PoisonOp::create(builder, loc, srcType); - for (auto &&[i, elem] : llvm::enumerate(src)) { + // Multiple elements narrower than dst: gather into a vector and bitcast. + unsigned elemBitWidth = getBitWidth(front.getType()); + assert(dstBitWidth % elemBitWidth == 0 && + "dst bit width must be a multiple of element bit width"); + int64_t numElements = dstBitWidth / elemBitWidth; + auto vecType = VectorType::get(numElements, front.getType()); + Value res = LLVM::PoisonOp::create(builder, loc, vecType); + for (auto i : llvm::seq(numElements)) { Value idx = createI32Constant(builder, loc, i); - res = LLVM::InsertElementOp::create(builder, loc, srcType, res, elem, idx); + res = LLVM::InsertElementOp::create(builder, loc, vecType, res, + src[offset++], idx); } if (res.getType() != dstType) @@ -468,6 +561,15 @@ Value mlir::LLVM::composeValue(OpBuilder &builder, Location loc, ValueRange src, return res; } +Value mlir::LLVM::composeValue(OpBuilder &builder, Location loc, ValueRange src, + Type dstType) { + assert(!src.empty() && "src range must not be empty"); + size_t offset = 0; + Value result = composeValueImpl(builder, loc, src, offset, dstType); + assert(offset == src.size() && "not all decomposed values were consumed"); + return result; +} + Value mlir::LLVM::getStridedElementPtr(OpBuilder &builder, Location loc, const LLVMTypeConverter &converter, MemRefType type, Value memRefDesc, diff --git a/mlir/test/Conversion/GPUToROCDL/gpu-to-rocdl.mlir b/mlir/test/Conversion/GPUToROCDL/gpu-to-rocdl.mlir index 6b20a442c30c5..1f958791b41bb 100755 --- a/mlir/test/Conversion/GPUToROCDL/gpu-to-rocdl.mlir +++ b/mlir/test/Conversion/GPUToROCDL/gpu-to-rocdl.mlir @@ -851,4 +851,73 @@ func.func @broadcast_4xi16(%arg0 : vector<4xi16>) -> vector<4xi16> { %0 = gpu.subgroup_broadcast %arg0, first_active_lane : vector<4xi16> func.return %0 : vector<4xi16> } + +// CHECK-LABEL: func @broadcast_2x2xi16 +// CHECK-SAME: (%[[ARG:.+]]: !llvm.array<2 x vector<2xi16>>) +func.func @broadcast_2x2xi16(%arg0 : vector<2x2xi16>) -> vector<2x2xi16> { + // CHECK-DAG: %[[E0:.+]] = llvm.extractvalue %[[ARG]][0] : !llvm.array<2 x vector<2xi16>> + // CHECK-DAG: %[[BC0:.+]] = llvm.bitcast %[[E0]] : vector<2xi16> to i32 + // CHECK-DAG: %[[E1:.+]] = llvm.extractvalue %[[ARG]][1] : !llvm.array<2 x vector<2xi16>> + // CHECK-DAG: %[[BC1:.+]] = llvm.bitcast %[[E1]] : vector<2xi16> to i32 + // CHECK: %[[R0:.+]] = rocdl.readfirstlane %[[BC0]] : i32 + // CHECK: %[[R1:.+]] = rocdl.readfirstlane %[[BC1]] : i32 + // CHECK: %[[POISON:.+]] = llvm.mlir.poison : !llvm.array<2 x vector<2xi16>> + // CHECK: %[[RBC0:.+]] = llvm.bitcast %[[R0]] : i32 to vector<2xi16> + // CHECK: %[[INS0:.+]] = llvm.insertvalue %[[RBC0]], %[[POISON]][0] : !llvm.array<2 x vector<2xi16>> + // CHECK: %[[RBC1:.+]] = llvm.bitcast %[[R1]] : i32 to vector<2xi16> + // CHECK: %[[INS1:.+]] = llvm.insertvalue %[[RBC1]], %[[INS0]][1] : !llvm.array<2 x vector<2xi16>> + // CHECK: llvm.return %[[INS1]] + %0 = gpu.subgroup_broadcast %arg0, first_active_lane : vector<2x2xi16> + func.return %0 : vector<2x2xi16> +} + +// CHECK-LABEL: func @broadcast_memref +func.func @broadcast_memref(%arg0 : memref) -> memref { + // CHECK-DAG: %[[PTR0:.+]] = llvm.extractvalue %{{.+}}[0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK-DAG: %[[PTR1:.+]] = llvm.extractvalue %{{.+}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK-DAG: %[[OFF:.+]] = llvm.extractvalue %{{.+}}[2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK-DAG: %[[OFFVEC:.+]] = llvm.bitcast %[[OFF]] : i64 to vector<2xi32> + // CHECK-DAG: %[[OFF0:.+]] = llvm.extractelement %[[OFFVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK-DAG: %[[OFF1:.+]] = llvm.extractelement %[[OFFVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK-DAG: %[[SZ_ARR:.+]] = llvm.extractvalue %{{.+}}[3] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK-DAG: %[[SZ:.+]] = llvm.extractvalue %[[SZ_ARR]][0] : !llvm.array<1 x i64> + // CHECK-DAG: %[[SZVEC:.+]] = llvm.bitcast %[[SZ]] : i64 to vector<2xi32> + // CHECK-DAG: %[[SZ0:.+]] = llvm.extractelement %[[SZVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK-DAG: %[[SZ1:.+]] = llvm.extractelement %[[SZVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK-DAG: %[[STR_ARR:.+]] = llvm.extractvalue %{{.+}}[4] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK-DAG: %[[STR:.+]] = llvm.extractvalue %[[STR_ARR]][0] : !llvm.array<1 x i64> + // CHECK-DAG: %[[STRVEC:.+]] = llvm.bitcast %[[STR]] : i64 to vector<2xi32> + // CHECK-DAG: %[[STR0:.+]] = llvm.extractelement %[[STRVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK-DAG: %[[STR1:.+]] = llvm.extractelement %[[STRVEC]][%{{.+}} : i32] : vector<2xi32> + // + // CHECK: %[[RPTR0:.+]] = rocdl.readfirstlane %[[PTR0]] : !llvm.ptr + // CHECK: %[[RPTR1:.+]] = rocdl.readfirstlane %[[PTR1]] : !llvm.ptr + // CHECK: %[[ROFF0:.+]] = rocdl.readfirstlane %[[OFF0]] : i32 + // CHECK: %[[ROFF1:.+]] = rocdl.readfirstlane %[[OFF1]] : i32 + // CHECK: %[[RSZ0:.+]] = rocdl.readfirstlane %[[SZ0]] : i32 + // CHECK: %[[RSZ1:.+]] = rocdl.readfirstlane %[[SZ1]] : i32 + // CHECK: %[[RSTR0:.+]] = rocdl.readfirstlane %[[STR0]] : i32 + // CHECK: %[[RSTR1:.+]] = rocdl.readfirstlane %[[STR1]] : i32 + // + // CHECK: %[[SOUT:.+]] = llvm.mlir.poison : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> + // CHECK: %[[S0:.+]] = llvm.insertvalue %[[RPTR0]], %[[SOUT]][0] + // CHECK: %[[S1:.+]] = llvm.insertvalue %[[RPTR1]], %[[S0]][1] + // CHECK: %[[OVEC:.+]] = llvm.insertelement %[[ROFF0]], %{{.+}}[%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[OVEC2:.+]] = llvm.insertelement %[[ROFF1]], %[[OVEC]][%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[OCAST:.+]] = llvm.bitcast %[[OVEC2]] : vector<2xi32> to i64 + // CHECK: %[[S2:.+]] = llvm.insertvalue %[[OCAST]], %[[S1]][2] + // CHECK: %[[SZVEC2:.+]] = llvm.insertelement %[[RSZ0]], %{{.+}}[%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[SZVEC3:.+]] = llvm.insertelement %[[RSZ1]], %[[SZVEC2]][%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[SZCAST:.+]] = llvm.bitcast %[[SZVEC3]] : vector<2xi32> to i64 + // CHECK: %[[SZA:.+]] = llvm.insertvalue %[[SZCAST]], %{{.+}}[0] : !llvm.array<1 x i64> + // CHECK: %[[S3:.+]] = llvm.insertvalue %[[SZA]], %[[S2]][3] + // CHECK: %[[STRVEC2:.+]] = llvm.insertelement %[[RSTR0]], %{{.+}}[%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[STRVEC3:.+]] = llvm.insertelement %[[RSTR1]], %[[STRVEC2]][%{{.+}} : i32] : vector<2xi32> + // CHECK: %[[STRCAST:.+]] = llvm.bitcast %[[STRVEC3]] : vector<2xi32> to i64 + // CHECK: %[[STR_ARR:.+]] = llvm.insertvalue %[[STRCAST]], %{{.+}}[0] : !llvm.array<1 x i64> + // CHECK: %[[S4:.+]] = llvm.insertvalue %[[STR_ARR]], %[[S3]][4] + // CHECK: llvm.return %[[S4]] + %0 = gpu.subgroup_broadcast %arg0, first_active_lane : memref + func.return %0 : memref +} } From c05e323be7caaadff6fdd09a2336be60e3041af1 Mon Sep 17 00:00:00 2001 From: Demetrius Kanios Date: Fri, 27 Feb 2026 10:52:01 -0800 Subject: [PATCH 27/58] [WebAssembly] Incorporate SCCs into WebAssemblyFixIrreducibleControlFlow (#181755) Rather than mapping out full "reachability" between blocks in a region to find loops and using `LoopBlocks` to find the bodies of said loops, use SCCs (strongly-connected components) to provide this information. This brings in LLVM's generic `SCCIterator` (which uses Tarjan's algorithm) as the implementation for sorting the basic blocks of the CFG into their SCCs. This PR greatly reduces the compile-time footprint of the pass, making memory use and time taken negliable where it might have previously caused stalls and OOM before (e.g. #47793, usagi-coffee/tree-sitter-abl#114) ------ Supersedes #179722 Fixes #47793 Fixes #165041 (probably) Thanks to @jkbz64 for the initial investigations (w/ AI; see #179722) into why this pass was slow and memory consuming and showing that SCCs were the key. Also thanks to the Cheerp compiler project for bringing `SCCIterator` to light in this context ([blog post](https://cheerp.io/blog/control-flow#fix-the-irreducible-control-flow), [implementation](https://github.com/leaningtech/cheerp-compiler/blob/master/llvm/lib/CheerpUtils/FixIrreducibleControlFlow.cpp)). --- .../WebAssemblyFixIrreducibleControlFlow.cpp | 273 +++++++++--------- 1 file changed, 144 insertions(+), 129 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp index 07171d472dc2d..0b9c4967149e4 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp @@ -18,17 +18,17 @@ /// The big picture: We recursively process each "region", defined as a group /// of blocks with a single entry and no branches back to that entry. A region /// may be the entire function body, or the inner part of a loop, i.e., the -/// loop's body without branches back to the loop entry. In each region we fix -/// up multi-entry loops by adding a new block that can dispatch to each of the -/// loop entries, based on the value of a label "helper" variable, and we -/// replace direct branches to the entries with assignments to the label -/// variable and a branch to the dispatch block. Then the dispatch block is the -/// single entry in the loop containing the previous multiple entries. After -/// ensuring all the loops in a region are reducible, we recurse into them. The -/// total time complexity of this pass is: -/// -/// O(NumBlocks * NumNestedLoops * NumIrreducibleLoops + -/// NumLoops * NumLoops) +/// loop's body without branches back to the loop entry. In each region we +/// identify all the strongly-connected components (SCCs). We fix up multi-entry +/// loops (SCCs) by adding a new block that can dispatch to each of the loop +/// entries, based on the value of a label "helper" variable, and we replace +/// direct branches to the entries with assignments to the label variable and a +/// branch to the dispatch block. Then the dispatch block is the single entry in +/// the loop containing the previous multiple entries. Each time we fix some +/// irreducibility, we recalculate the SCCs. After ensuring all the SCCs in a +/// region are reducible, we recurse into them. The total time complexity of +/// this pass is roughly: +/// O((NumBlocks + NumEdges) * (NumNestedLoops + NumIrreducibleLoops)) /// /// This pass is similar to what the Relooper [1] does. Both identify looping /// code that requires multiple entries, and resolve it in a similar way (in @@ -55,9 +55,12 @@ #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "WebAssembly.h" #include "WebAssemblySubtarget.h" +#include "llvm/ADT/SCCIterator.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Support/Debug.h" +#include using namespace llvm; #define DEBUG_TYPE "wasm-fix-irreducible-control-flow" @@ -78,9 +81,15 @@ static BlockVector getSortedEntries(const BlockSet &Entries) { return SortedEntries; } -// Calculates reachability in a region. Ignores branches to blocks outside of -// the region, and ignores branches to the region entry (for the case where -// the region is the inner part of a loop). +struct ReachabilityNode { + MachineBasicBlock *MBB; + SmallVector Succs; + unsigned SCCId = std::numeric_limits::max(); +}; + +// Analyzes the SCC (strongly-connected component) structure in a region. +// Ignores branches to blocks outside of the region, and ignores branches to the +// region entry (for the case where the region is the inner part of a loop). class ReachabilityGraph { public: ReachabilityGraph(MachineBasicBlock *Entry, const BlockSet &Blocks) @@ -98,137 +107,139 @@ class ReachabilityGraph { calculate(); } - bool canReach(MachineBasicBlock *From, MachineBasicBlock *To) const { - assert(inRegion(From) && inRegion(To)); - auto I = Reachable.find(From); - if (I == Reachable.end()) - return false; - return I->second.count(To); - } - - // "Loopers" are blocks that are in a loop. We detect these by finding blocks - // that can reach themselves. - const BlockSet &getLoopers() const { return Loopers; } - // Get all blocks that are loop entries. const BlockSet &getLoopEntries() const { return LoopEntries; } + const BlockSet &getLoopEntriesForSCC(unsigned SCCId) const { + return LoopEntriesBySCC[SCCId]; + } - // Get all blocks that enter a particular loop from outside. - const BlockSet &getLoopEnterers(MachineBasicBlock *LoopEntry) const { - assert(inRegion(LoopEntry)); - auto I = LoopEnterers.find(LoopEntry); - assert(I != LoopEnterers.end()); - return I->second; + unsigned getSCCId(MachineBasicBlock *MBB) const { + return getNode(MBB)->SCCId; } + friend struct GraphTraits; + private: MachineBasicBlock *Entry; const BlockSet &Blocks; - BlockSet Loopers, LoopEntries; - DenseMap LoopEnterers; + BlockSet LoopEntries; + SmallVector LoopEntriesBySCC; bool inRegion(MachineBasicBlock *MBB) const { return Blocks.count(MBB); } - // Maps a block to all the other blocks it can reach. - DenseMap Reachable; + SmallVector Nodes; + DenseMap MBBToNodeMap; - void calculate() { - // Reachability computation work list. Contains pairs of recent additions - // (A, B) where we just added a link A => B. - using BlockPair = std::pair; - SmallVector WorkList; + ReachabilityNode *getNode(MachineBasicBlock *MBB) const { + return MBBToNodeMap.at(MBB); + } - // Add all relevant direct branches. - for (auto *MBB : Blocks) { - for (auto *Succ : MBB->successors()) { - if (Succ != Entry && inRegion(Succ)) { - Reachable[MBB].insert(Succ); - WorkList.emplace_back(MBB, Succ); - } - } - } + void calculate(); +}; +} // end anonymous namespace - while (!WorkList.empty()) { - MachineBasicBlock *MBB, *Succ; - std::tie(MBB, Succ) = WorkList.pop_back_val(); - assert(inRegion(MBB) && Succ != Entry && inRegion(Succ)); - if (MBB != Entry) { - // We recently added MBB => Succ, and that means we may have enabled - // Pred => MBB => Succ. - for (auto *Pred : MBB->predecessors()) { - if (Reachable[Pred].insert(Succ).second) { - WorkList.emplace_back(Pred, Succ); - } - } - } - } +namespace llvm { +template <> struct GraphTraits { + using NodeRef = ReachabilityNode *; + using ChildIteratorType = SmallVectorImpl::iterator; - // Blocks that can return to themselves are in a loop. - for (auto *MBB : Blocks) { - if (canReach(MBB, MBB)) { - Loopers.insert(MBB); - } - } - assert(!Loopers.count(Entry)); - - // Find the loop entries - loopers reachable from blocks not in that loop - - // and those outside blocks that reach them, the "loop enterers". - for (auto *Looper : Loopers) { - for (auto *Pred : Looper->predecessors()) { - // Pred can reach Looper. If Looper can reach Pred, it is in the loop; - // otherwise, it is a block that enters into the loop. - if (!canReach(Looper, Pred)) { - LoopEntries.insert(Looper); - LoopEnterers[Looper].insert(Pred); - } - } - } + static NodeRef getEntryNode(ReachabilityGraph *G) { + return G->getNode(G->Entry); + } + + static inline ChildIteratorType child_begin(NodeRef N) { + return N->Succs.begin(); + } + + static inline ChildIteratorType child_end(NodeRef N) { + return N->Succs.end(); } }; +} // end namespace llvm -// Finds the blocks in a single-entry loop, given the loop entry and the -// list of blocks that enter the loop. -class LoopBlocks { -public: - LoopBlocks(MachineBasicBlock *Entry, const BlockSet &Enterers) - : Entry(Entry), Enterers(Enterers) { - calculate(); +namespace { + +void ReachabilityGraph::calculate() { + auto NumBlocks = Blocks.size(); + Nodes.assign(NumBlocks, {}); + + MBBToNodeMap.clear(); + MBBToNodeMap.reserve(NumBlocks); + + // Initialize mappings. + unsigned MBBIdx = 0; + for (auto *MBB : Blocks) { + auto &Node = Nodes[MBBIdx++]; + + Node.MBB = MBB; + MBBToNodeMap[MBB] = &Node; } - BlockSet &getBlocks() { return Blocks; } + // Add all relevant direct branches. + MBBIdx = 0; + for (auto *MBB : Blocks) { + auto &Node = Nodes[MBBIdx++]; -private: - MachineBasicBlock *Entry; - const BlockSet &Enterers; + for (auto *Succ : MBB->successors()) { + if (Succ != Entry && inRegion(Succ)) { + Node.Succs.push_back(getNode(Succ)); + } + } + } - BlockSet Blocks; + unsigned CurrSCCIdx = 0; + for (auto &SCC : make_range(scc_begin(this), scc_end(this))) { + LoopEntriesBySCC.push_back({}); + auto &SCCLoopEntries = LoopEntriesBySCC.back(); - void calculate() { - // Going backwards from the loop entry, if we ignore the blocks entering - // from outside, we will traverse all the blocks in the loop. - BlockVector WorkList; - BlockSet AddedToWorkList; - Blocks.insert(Entry); - for (auto *Pred : Entry->predecessors()) { - if (!Enterers.count(Pred)) { - WorkList.push_back(Pred); - AddedToWorkList.insert(Pred); + for (auto *Node : SCC) { + // Make sure nodes are only ever assigned one SCC + assert(Node->SCCId == std::numeric_limits::max()); + + Node->SCCId = CurrSCCIdx; + } + + bool SelfLoop = false; + if (SCC.size() == 1) { + auto &Node = SCC[0]; + + for (auto *Succ : Node->Succs) { + if (Succ == Node) { + SelfLoop = true; + break; + } } } - while (!WorkList.empty()) { - auto *MBB = WorkList.pop_back_val(); - assert(!Enterers.count(MBB)); - if (Blocks.insert(MBB).second) { - for (auto *Pred : MBB->predecessors()) { - if (AddedToWorkList.insert(Pred).second) - WorkList.push_back(Pred); + // Blocks outside any (multi-block) loop will be isolated in their own + // single-element SCC. Thus blocks that are in a loop are those in + // multi-element SCCs or are self-looping. + if (SCC.size() > 1 || SelfLoop) { + // Find the loop entries - loop body blocks with predecessors outside + // their SCC + for (auto *Node : SCC) { + if (Node->MBB == Entry) + continue; + + for (auto *Pred : Node->MBB->predecessors()) { + // This test is accurate despite not having assigned all nodes an SCC + // yet. We only care if a node has been assigned into this SCC or not. + if (getSCCId(Pred) != CurrSCCIdx) { + LoopEntries.insert(Node->MBB); + SCCLoopEntries.insert(Node->MBB); + } } } } + ++CurrSCCIdx; } -}; + + // Make sure all nodes have been processed + for (auto &Node : Nodes) { + assert(Node.SCCId != std::numeric_limits::max()); + } +} class WebAssemblyFixIrreducibleControlFlow final : public MachineFunctionPass { StringRef getPassName() const override { @@ -240,7 +251,7 @@ class WebAssemblyFixIrreducibleControlFlow final : public MachineFunctionPass { bool processRegion(MachineBasicBlock *Entry, BlockSet &Blocks, MachineFunction &MF); - void makeSingleEntryLoop(BlockSet &Entries, BlockSet &Blocks, + void makeSingleEntryLoop(const BlockSet &Entries, BlockSet &Blocks, MachineFunction &MF, const ReachabilityGraph &Graph); public: @@ -261,7 +272,7 @@ bool WebAssemblyFixIrreducibleControlFlow::processRegion( for (auto *LoopEntry : getSortedEntries(Graph.getLoopEntries())) { // Find mutual entries - all entries which can reach this one, and // are reached by it (that always includes LoopEntry itself). All mutual - // entries must be in the same loop, so if we have more than one, then we + // entries must be in the same SCC, so if we have more than one, then we // have irreducible control flow. // // (Note that we need to sort the entries here, as otherwise the order can @@ -284,15 +295,8 @@ bool WebAssemblyFixIrreducibleControlFlow::processRegion( // a group of blocks all of whom can reach each other. (We'll see the // irreducibility after removing branches to the top of that enclosing // loop.) - BlockSet MutualLoopEntries; - MutualLoopEntries.insert(LoopEntry); - for (auto *OtherLoopEntry : Graph.getLoopEntries()) { - if (OtherLoopEntry != LoopEntry && - Graph.canReach(LoopEntry, OtherLoopEntry) && - Graph.canReach(OtherLoopEntry, LoopEntry)) { - MutualLoopEntries.insert(OtherLoopEntry); - } - } + auto &MutualLoopEntries = + Graph.getLoopEntriesForSCC(Graph.getSCCId(LoopEntry)); if (MutualLoopEntries.size() > 1) { makeSingleEntryLoop(MutualLoopEntries, Blocks, MF, Graph); @@ -301,6 +305,7 @@ bool WebAssemblyFixIrreducibleControlFlow::processRegion( break; } } + // Only go on to actually process the inner loops when we are done // removing irreducible control flow and changing the graph. Modifying // the graph as we go is possible, and that might let us avoid looking at @@ -312,14 +317,22 @@ bool WebAssemblyFixIrreducibleControlFlow::processRegion( } for (auto *LoopEntry : Graph.getLoopEntries()) { - LoopBlocks InnerBlocks(LoopEntry, Graph.getLoopEnterers(LoopEntry)); + BlockSet InnerBlocks; + + auto EntrySCCId = Graph.getSCCId(LoopEntry); + for (auto *Block : Blocks) { + if (EntrySCCId == Graph.getSCCId(Block)) { + InnerBlocks.insert(Block); + } + } + // Each of these calls to processRegion may change the graph, but are // guaranteed not to interfere with each other. The only changes we make // to the graph are to add blocks on the way to a loop entry. As the // loops are disjoint, that means we may only alter branches that exit // another loop, which are ignored when recursing into that other loop // anyhow. - if (processRegion(LoopEntry, InnerBlocks.getBlocks(), MF)) { + if (processRegion(LoopEntry, InnerBlocks, MF)) { Changed = true; } } @@ -335,7 +348,7 @@ bool WebAssemblyFixIrreducibleControlFlow::processRegion( // ReachabilityGraph; this will be updated in the caller of this function as // needed. void WebAssemblyFixIrreducibleControlFlow::makeSingleEntryLoop( - BlockSet &Entries, BlockSet &Blocks, MachineFunction &MF, + const BlockSet &Entries, BlockSet &Blocks, MachineFunction &MF, const ReachabilityGraph &Graph) { assert(Entries.size() >= 2); @@ -401,10 +414,12 @@ void WebAssemblyFixIrreducibleControlFlow::makeSingleEntryLoop( // This set stores predecessors within this loop. DenseSet InLoop; for (auto *Pred : AllPreds) { + auto PredSCCId = Graph.getSCCId(Pred); + for (auto *Entry : Pred->successors()) { if (!Entries.count(Entry)) continue; - if (Graph.canReach(Entry, Pred)) { + if (Graph.getSCCId(Entry) == PredSCCId) { InLoop.insert(Pred); break; } From dce48f2653cb81883a24ff5babdcac5bcb91725c Mon Sep 17 00:00:00 2001 From: Amit Kumar Pandey Date: Sat, 28 Feb 2026 00:22:18 +0530 Subject: [PATCH 28/58] [OpenMP] Enable internalization of 'ockl.bc' for OpenMP (#183685) Fix linking of 'ockl.bc' for OpenMP by switching from `-mlink-bitcode-file` to `-mlink-builtin-bitcode` --- clang/lib/Driver/ToolChains/AMDGPU.cpp | 2 +- clang/test/Driver/amdgpu-openmp-sanitize-options.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 377e851be6e26..f69c745680ee8 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -1043,7 +1043,7 @@ RocmInstallationDetector::getCommonBitcodeLibs( if (!Pref.IsOpenMP) AddBCLib(getOCKLPath()); else if (Pref.GPUSan && Pref.IsOpenMP) - AddBCLib(getOCKLPath(), false); + AddBCLib(getOCKLPath()); AddBCLib(getUnsafeMathPath(Pref.UnsafeMathOpt || Pref.FastRelaxedMath)); AddBCLib(getFiniteOnlyPath(Pref.FiniteOnly || Pref.FastRelaxedMath)); AddBCLib(getWavefrontSize64Path(Pref.Wave64)); diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c b/clang/test/Driver/amdgpu-openmp-sanitize-options.c index 8fb53121e92b4..141a4acdd4eea 100644 --- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c +++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c @@ -104,7 +104,7 @@ // HOSTSANCOMBINATION: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address,fuzzer,fuzzer-no-link".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}} // HOSTSANCOMBINATION2: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address,fuzzer,fuzzer-no-link,leak".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}} -// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-builtin-bitcode" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} +// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-builtin-bitcode" "[^"]*asanrtl.bc".* "-mlink-builtin-bitcode" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} // NOGPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-target-cpu" "(gfx908|gfx900)".* "-fopenmp".* "-x" "c".*}} // SAN: {{"[^"]*llvm-offload-binary[^"]*" "-o".* "--image=file=.*.bc,triple=amdgcn-amd-amdhsa,arch=(gfx908|gfx1250|gfx1251)(:xnack\-|:xnack\+)?,kind=openmp(,feature=(\-xnack|\+xnack))?"}} From 403fd7679f80c97c13e992b32a6762bfc92641cb Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Fri, 27 Feb 2026 10:55:20 -0800 Subject: [PATCH 29/58] [SlotIndexes] Further pack indices to improve spill placement time (#182640) This patch makes it so that renumbering indices when inserting instructions into the SlotIndexes analysis renumbers the entire list if the list is otherwise densely packed. This fixes a case we saw on AArch64 with a lot of spills where every single spill instruction insertion required a renumbering of most of the instructions in a large function, making the operation approximately quadratic. This is not NFC as heuristics depend on the SlotIndex numbers, although this should mostly be a wash as LRs should be extended ~equally. --- llvm/lib/CodeGen/SlotIndexes.cpp | 9 + .../misched-detail-resource-booking-01.mir | 76 +- .../CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll | 2640 +++++++++-------- llvm/test/CodeGen/AMDGPU/remat-sop.mir | 12 +- llvm/test/CodeGen/X86/statepoint-live-in.ll | 4 +- llvm/test/CodeGen/X86/statepoint-regs.ll | 4 +- 6 files changed, 1389 insertions(+), 1356 deletions(-) diff --git a/llvm/lib/CodeGen/SlotIndexes.cpp b/llvm/lib/CodeGen/SlotIndexes.cpp index 62e7f86a846ac..6861c6f0e9b02 100644 --- a/llvm/lib/CodeGen/SlotIndexes.cpp +++ b/llvm/lib/CodeGen/SlotIndexes.cpp @@ -174,6 +174,7 @@ void SlotIndexes::renumberIndexes(IndexList::iterator curItr) { IndexList::iterator startItr = std::prev(curItr); unsigned index = startItr->getIndex(); + unsigned BeginIndex = index; do { curItr->setIndex(index += Space); ++curItr; @@ -182,6 +183,14 @@ void SlotIndexes::renumberIndexes(IndexList::iterator curItr) { LLVM_DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << startItr->getIndex() << '-' << index << " ***\n"); + + // If we repack more than 20% of a function, add spacing in between the + // instructions so that future renumberings are able to catch up + // without also renumbering so much. + if (index - BeginIndex > + (getLastIndex().getIndex() - getZeroIndex().getIndex()) / 5) + packIndexes(); + ++NumLocalRenum; } diff --git a/llvm/test/CodeGen/AArch64/misched-detail-resource-booking-01.mir b/llvm/test/CodeGen/AArch64/misched-detail-resource-booking-01.mir index 2afc25f895432..31e14e204daa9 100644 --- a/llvm/test/CodeGen/AArch64/misched-detail-resource-booking-01.mir +++ b/llvm/test/CodeGen/AArch64/misched-detail-resource-booking-01.mir @@ -1665,32 +1665,32 @@ body: | # CHECK-NEXT: SU(12) [TopReadyCycle = 0, BottomReadyCycle = 3]: $q1 = COPY %12:fpr128 # CHECK-EMPTY: # CHECK-NEXT: ********** INTERVALS ********** -# CHECK-NEXT: B0 [0B,48r:0)[192r,224r:1) 0@0B-phi 1@192r -# CHECK-NEXT: B1 [0B,88r:0)[208r,224r:1) 0@0B-phi 1@208r -# CHECK-NEXT: B2 [0B,96r:0) 0@0B-phi -# CHECK-NEXT: B0_HI [0B,48r:0)[192r,224r:1) 0@0B-phi 1@192r -# CHECK-NEXT: H0_HI [0B,48r:0)[192r,224r:1) 0@0B-phi 1@192r -# CHECK-NEXT: S0_HI [0B,48r:0)[192r,224r:1) 0@0B-phi 1@192r -# CHECK-NEXT: B1_HI [0B,88r:0)[208r,224r:1) 0@0B-phi 1@208r -# CHECK-NEXT: H1_HI [0B,88r:0)[208r,224r:1) 0@0B-phi 1@208r -# CHECK-NEXT: S1_HI [0B,88r:0)[208r,224r:1) 0@0B-phi 1@208r -# CHECK-NEXT: B2_HI [0B,96r:0) 0@0B-phi -# CHECK-NEXT: H2_HI [0B,96r:0) 0@0B-phi -# CHECK-NEXT: S2_HI [0B,96r:0) 0@0B-phi -# CHECK-NEXT: D0_HI [0B,48r:0)[192r,224r:1) 0@0B-phi 1@192r -# CHECK-NEXT: D1_HI [0B,88r:0)[208r,224r:1) 0@0B-phi 1@208r -# CHECK-NEXT: D2_HI [0B,96r:0) 0@0B-phi -# CHECK-NEXT: %0 [48r,168r:0) 0@48r weight:0.000000e+00 -# CHECK-NEXT: %1 [88r,120r:0) 0@88r weight:0.000000e+00 -# CHECK-NEXT: %2 [96r,128r:0) 0@96r weight:0.000000e+00 -# CHECK-NEXT: %3 [104r,176r:0) 0@104r weight:0.000000e+00 -# CHECK-NEXT: %6 [80r,128r:0) 0@80r weight:0.000000e+00 -# CHECK-NEXT: %7 [128r,160r:0) 0@128r weight:0.000000e+00 -# CHECK-NEXT: %8 [120r,136r:0) 0@120r weight:0.000000e+00 -# CHECK-NEXT: %9 [136r,168r:0) 0@136r weight:0.000000e+00 -# CHECK-NEXT: %10 [168r,192r:0) 0@168r weight:0.000000e+00 -# CHECK-NEXT: %11 [160r,176r:0) 0@160r weight:0.000000e+00 -# CHECK-NEXT: %12 [176r,208r:0) 0@176r weight:0.000000e+00 +# CHECK-NEXT: B0 [0B,48r:0)[272r,304r:1) 0@0B-phi 1@272r +# CHECK-NEXT: B1 [0B,96r:0)[288r,304r:1) 0@0B-phi 1@288r +# CHECK-NEXT: B2 [0B,112r:0) 0@0B-phi +# CHECK-NEXT: B0_HI [0B,48r:0)[272r,304r:1) 0@0B-phi 1@272r +# CHECK-NEXT: H0_HI [0B,48r:0)[272r,304r:1) 0@0B-phi 1@272r +# CHECK-NEXT: S0_HI [0B,48r:0)[272r,304r:1) 0@0B-phi 1@272r +# CHECK-NEXT: B1_HI [0B,96r:0)[288r,304r:1) 0@0B-phi 1@288r +# CHECK-NEXT: H1_HI [0B,96r:0)[288r,304r:1) 0@0B-phi 1@288r +# CHECK-NEXT: S1_HI [0B,96r:0)[288r,304r:1) 0@0B-phi 1@288r +# CHECK-NEXT: B2_HI [0B,112r:0) 0@0B-phi +# CHECK-NEXT: H2_HI [0B,112r:0) 0@0B-phi +# CHECK-NEXT: S2_HI [0B,112r:0) 0@0B-phi +# CHECK-NEXT: D0_HI [0B,48r:0)[272r,304r:1) 0@0B-phi 1@272r +# CHECK-NEXT: D1_HI [0B,96r:0)[288r,304r:1) 0@0B-phi 1@288r +# CHECK-NEXT: D2_HI [0B,112r:0) 0@0B-phi +# CHECK-NEXT: %0 [48r,240r:0) 0@48r weight:0.000000e+00 +# CHECK-NEXT: %1 [96r,160r:0) 0@96r weight:0.000000e+00 +# CHECK-NEXT: %2 [112r,176r:0) 0@112r weight:0.000000e+00 +# CHECK-NEXT: %3 [128r,256r:0) 0@128r weight:0.000000e+00 +# CHECK-NEXT: %6 [80r,176r:0) 0@80r weight:0.000000e+00 +# CHECK-NEXT: %7 [176r,224r:0) 0@176r weight:0.000000e+00 +# CHECK-NEXT: %8 [160r,192r:0) 0@160r weight:0.000000e+00 +# CHECK-NEXT: %9 [192r,240r:0) 0@192r weight:0.000000e+00 +# CHECK-NEXT: %10 [240r,272r:0) 0@240r weight:0.000000e+00 +# CHECK-NEXT: %11 [224r,256r:0) 0@224r weight:0.000000e+00 +# CHECK-NEXT: %12 [256r,288r:0) 0@256r weight:0.000000e+00 # CHECK-NEXT: RegMasks: # CHECK-NEXT: ********** MACHINEINSTRS ********** # CHECK-NEXT: # Machine code for function umull_and_v8i32: IsSSA, NoPHIs, TracksLiveness @@ -1700,17 +1700,17 @@ body: | # CHECK-NEXT: liveins: $q0, $q1, $q2 # CHECK-NEXT: 48B %0:fpr128 = COPY $q0 # CHECK-NEXT: 80B %6:fpr128 = MOVIv2d_ns 17 -# CHECK-NEXT: 88B %1:fpr128 = COPY $q1 -# CHECK-NEXT: 96B %2:fpr128 = COPY $q2 -# CHECK-NEXT: 104B %3:fpr128 = EXTv16i8 %0:fpr128, %0:fpr128, 8 -# CHECK-NEXT: 120B %8:fpr128 = ANDv16i8 %1:fpr128, %6:fpr128 -# CHECK-NEXT: 128B %7:fpr128 = ANDv16i8 %2:fpr128, %6:fpr128 -# CHECK-NEXT: 136B %9:fpr64 = XTNv4i16 %8:fpr128 -# CHECK-NEXT: 160B %11:fpr64 = XTNv4i16 %7:fpr128 -# CHECK-NEXT: 168B %10:fpr128 = UMULLv4i16_v4i32 %0.dsub:fpr128, %9:fpr64 -# CHECK-NEXT: 176B %12:fpr128 = UMULLv4i16_v4i32 %3.dsub:fpr128, %11:fpr64 -# CHECK-NEXT: 192B $q0 = COPY %10:fpr128 -# CHECK-NEXT: 208B $q1 = COPY %12:fpr128 -# CHECK-NEXT: 224B RET_ReallyLR implicit $q0, implicit $q1 +# CHECK-NEXT: 96B %1:fpr128 = COPY $q1 +# CHECK-NEXT: 112B %2:fpr128 = COPY $q2 +# CHECK-NEXT: 128B %3:fpr128 = EXTv16i8 %0:fpr128, %0:fpr128, 8 +# CHECK-NEXT: 160B %8:fpr128 = ANDv16i8 %1:fpr128, %6:fpr128 +# CHECK-NEXT: 176B %7:fpr128 = ANDv16i8 %2:fpr128, %6:fpr128 +# CHECK-NEXT: 192B %9:fpr64 = XTNv4i16 %8:fpr128 +# CHECK-NEXT: 224B %11:fpr64 = XTNv4i16 %7:fpr128 +# CHECK-NEXT: 240B %10:fpr128 = UMULLv4i16_v4i32 %0.dsub:fpr128, %9:fpr64 +# CHECK-NEXT: 256B %12:fpr128 = UMULLv4i16_v4i32 %3.dsub:fpr128, %11:fpr64 +# CHECK-NEXT: 272B $q0 = COPY %10:fpr128 +# CHECK-NEXT: 288B $q1 = COPY %12:fpr128 +# CHECK-NEXT: 304B RET_ReallyLR implicit $q0, implicit $q1 # CHECK-EMPTY: # CHECK-NEXT: # End machine code for function umull_and_v8i32. diff --git a/llvm/test/CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll b/llvm/test/CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll index 1b1f7fcadc540..4506c54f7ae11 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll @@ -140485,94 +140485,144 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:344 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:340 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:336 ; 4-byte Folded Spill -; VI-NEXT: v_mov_b32_e32 v41, v28 -; VI-NEXT: v_mov_b32_e32 v31, v1 -; VI-NEXT: v_mov_b32_e32 v28, v0 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:332 +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v22, v1 +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:332 ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:8 ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:248 -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v32 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:4 ; VI-NEXT: s_and_b64 s[4:5], vcc, exec -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:244 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:240 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:236 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:224 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:220 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:212 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:204 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:200 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:196 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:292 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:288 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:188 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:184 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:284 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:180 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:280 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:176 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:276 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:172 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:272 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:268 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:164 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:264 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:156 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:152 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:260 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:256 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:252 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:248 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:244 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:240 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:236 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:224 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:220 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:212 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:204 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:200 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:196 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:188 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:184 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:180 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:176 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:172 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:164 +; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:156 +; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:152 ; VI-NEXT: buffer_load_ushort v60, off, s[0:3], s32 offset:148 -; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:144 -; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:140 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:136 +; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:144 +; VI-NEXT: buffer_load_ushort v41, off, s[0:3], s32 offset:140 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:136 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:132 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:128 +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:132 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:128 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v43, off, s[0:3], s32 offset:124 ; VI-NEXT: buffer_load_ushort v45, off, s[0:3], s32 offset:120 ; VI-NEXT: buffer_load_ushort v56, off, s[0:3], s32 offset:116 @@ -140588,223 +140638,158 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: buffer_load_ushort v52, off, s[0:3], s32 offset:76 ; VI-NEXT: buffer_load_ushort v37, off, s[0:3], s32 offset:72 ; VI-NEXT: buffer_load_ushort v50, off, s[0:3], s32 offset:68 -; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:64 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:64 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v48, off, s[0:3], s32 offset:60 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:56 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:56 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v38, off, s[0:3], s32 offset:52 -; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:48 -; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 -; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:40 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:36 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:32 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:28 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:48 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:24 -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:20 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:16 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:12 -; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:40 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:36 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:28 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:24 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:20 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:16 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:292 -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:620 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:288 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:284 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:280 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:276 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:272 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:268 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:12 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:264 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:260 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:256 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:252 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:836 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:840 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill ; VI-NEXT: s_cbranch_scc0 .LBB89_4 ; VI-NEXT: ; %bb.1: ; %cmp.false ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v57, v61 -; VI-NEXT: v_mov_b32_e32 v61, v3 -; VI-NEXT: v_mov_b32_e32 v33, v34 -; VI-NEXT: v_mov_b32_e32 v34, v2 +; VI-NEXT: v_perm_b32 v6, v6, v7, s4 +; VI-NEXT: v_perm_b32 v7, v10, v11, s4 +; VI-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v58, v24 +; VI-NEXT: v_mov_b32_e32 v24, v3 +; VI-NEXT: v_mov_b32_e32 v42, v2 ; VI-NEXT: v_perm_b32 v4, v4, v5, s4 ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 -; VI-NEXT: v_perm_b32 v5, v34, v61, s4 +; VI-NEXT: v_perm_b32 v5, v42, v24, s4 ; VI-NEXT: v_or_b32_e32 v4, v5, v4 ; VI-NEXT: v_perm_b32 v5, v8, v9, s4 ; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 -; VI-NEXT: v_perm_b32 v6, v6, v7, s4 ; VI-NEXT: v_or_b32_e32 v5, v6, v5 ; VI-NEXT: v_perm_b32 v6, v12, v13, s4 ; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 -; VI-NEXT: v_perm_b32 v7, v10, v11, s4 ; VI-NEXT: v_or_b32_e32 v6, v7, v6 ; VI-NEXT: v_perm_b32 v7, v16, v17, s4 +; VI-NEXT: v_mov_b32_e32 v1, s17 +; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 ; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: v_perm_b32 v8, v14, v15, s4 +; VI-NEXT: v_perm_b32 v62, s16, v1, v3 +; VI-NEXT: v_mov_b32_e32 v1, s19 ; VI-NEXT: v_or_b32_e32 v7, v8, v7 ; VI-NEXT: v_perm_b32 v8, v20, v21, s4 +; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: v_perm_b32 v9, v18, v19, s4 +; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_or_b32_e32 v8, v9, v8 -; VI-NEXT: v_perm_b32 v9, v24, v25, s4 +; VI-NEXT: v_perm_b32 v9, v58, v25, s4 +; VI-NEXT: v_mov_b32_e32 v59, v0 +; VI-NEXT: buffer_store_dword v34, off, s[0:3], s32 offset:844 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v34, v28 +; VI-NEXT: v_or_b32_e32 v0, v62, v1 ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 -; VI-NEXT: v_perm_b32 v10, v22, v23, s4 -; VI-NEXT: v_or_b32_e32 v9, v10, v9 -; VI-NEXT: v_perm_b32 v10, v41, v29, s4 -; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v11, v26, v27, s4 -; VI-NEXT: v_or_b32_e32 v10, v11, v10 -; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v17, v35, v53, s4 ; VI-NEXT: v_lshlrev_b32_e32 v17, 16, v17 ; VI-NEXT: v_perm_b32 v19, v40, v51, s4 -; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v16, v48, v33, s4 ; VI-NEXT: v_or_b32_e32 v17, v19, v17 -; VI-NEXT: v_mov_b32_e32 v40, v55 ; VI-NEXT: v_perm_b32 v19, v47, v55, s4 -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v21, v58, v59, s4 -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v32, v62 -; VI-NEXT: v_mov_b32_e32 v62, v28 -; VI-NEXT: v_mov_b32_e32 v28, v31 -; VI-NEXT: v_perm_b32 v28, v62, v28, s4 -; VI-NEXT: v_mov_b32_e32 v62, v63 -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v28, v59, v22, s4 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: v_perm_b32 v21, v41, v46, s4 ; VI-NEXT: v_perm_b32 v18, v52, v39, s4 -; VI-NEXT: v_perm_b32 v15, v36, v32, s4 -; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v1, s19 +; VI-NEXT: v_perm_b32 v22, v32, v44, s4 ; VI-NEXT: v_mov_b32_e32 v31, s23 -; VI-NEXT: v_mov_b32_e32 v0, s17 -; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_mov_b32_e32 v2, s21 ; VI-NEXT: v_perm_b32 v31, s22, v31, v3 -; VI-NEXT: v_perm_b32 v0, s16, v0, v3 -; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_perm_b32 v2, s20, v2, v3 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 -; VI-NEXT: v_or_b32_e32 v0, v0, v1 ; VI-NEXT: v_or_b32_e32 v1, v2, v31 ; VI-NEXT: v_mov_b32_e32 v31, s27 ; VI-NEXT: v_mov_b32_e32 v2, s25 @@ -140816,43 +140801,58 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: v_perm_b32 v3, s28, v31, v3 ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: v_or_b32_e32 v3, v3, v28 +; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v62 -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_perm_b32 v11, v11, v12, s4 +; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:844 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v10, v10, v23, s4 +; VI-NEXT: v_or_b32_e32 v9, v10, v9 +; VI-NEXT: v_perm_b32 v10, v34, v29, s4 +; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: v_or_b32_e32 v10, v11, v10 +; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_mov_b32_e32 v63, v14 -; VI-NEXT: s_waitcnt vmcnt(9) -; VI-NEXT: v_perm_b32 v22, v44, v22, s4 -; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v15, v36, v62, s4 ; VI-NEXT: s_waitcnt vmcnt(4) -; VI-NEXT: v_mov_b32_e32 v43, v41 +; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(3) +; VI-NEXT: v_perm_b32 v16, v48, v16, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v11, v12, v11, s4 +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v30, v12, s4 ; VI-NEXT: v_or_b32_e32 v11, v12, v11 -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v12, v13, v12, s4 +; VI-NEXT: v_perm_b32 v12, v12, v13, s4 +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 -; VI-NEXT: v_perm_b32 v13, v14, v62, s4 +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v53, v61 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v13, v13, v61, s4 ; VI-NEXT: v_or_b32_e32 v12, v13, v12 -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v62, v32 +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v13, v13, v57, s4 -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v13, v13, v14, s4 +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v14, v61, v57, s4 +; VI-NEXT: v_perm_b32 v14, v14, v59, s4 ; VI-NEXT: v_or_b32_e32 v13, v14, v13 -; VI-NEXT: v_perm_b32 v14, v38, v41, s4 +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v14, v38, v14, s4 ; VI-NEXT: v_lshlrev_b32_e32 v14, 16, v14 ; VI-NEXT: v_or_b32_e32 v14, v15, v14 ; VI-NEXT: v_perm_b32 v15, v50, v37, s4 @@ -140862,115 +140862,114 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: v_lshlrev_b32_e32 v16, 16, v16 ; VI-NEXT: v_or_b32_e32 v16, v18, v16 ; VI-NEXT: v_perm_b32 v18, v56, v45, s4 -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 ; VI-NEXT: v_or_b32_e32 v18, v19, v18 -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v54, v63 -; VI-NEXT: v_mov_b32_e32 v45, v33 +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v19, v42, v56, s4 +; VI-NEXT: v_perm_b32 v19, v63, v56, s4 ; VI-NEXT: v_lshlrev_b32_e32 v19, 16, v19 ; VI-NEXT: v_or_b32_e32 v19, v20, v19 ; VI-NEXT: v_perm_b32 v20, v60, v47, s4 ; VI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 ; VI-NEXT: v_or_b32_e32 v20, v21, v20 -; VI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_perm_b32 v21, v33, v57, s4 +; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 +; VI-NEXT: v_or_b32_e32 v21, v22, v21 +; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(2) ; VI-NEXT: v_perm_b32 v42, v51, v37, s4 ; VI-NEXT: v_mov_b32_e32 v41, v36 ; VI-NEXT: v_mov_b32_e32 v32, v50 ; VI-NEXT: v_mov_b32_e32 v33, v51 -; VI-NEXT: v_mov_b32_e32 v60, v31 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v21, v46, v21, s4 -; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 -; VI-NEXT: v_or_b32_e32 v21, v22, v21 -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v22, v23, v22, s4 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v22, 16, v22 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 ; VI-NEXT: v_or_b32_e32 v22, v23, v22 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 ; VI-NEXT: v_or_b32_e32 v23, v24, v23 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v24, 16, v24 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 ; VI-NEXT: v_or_b32_e32 v24, v25, v24 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 ; VI-NEXT: v_or_b32_e32 v25, v26, v25 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 ; VI-NEXT: v_or_b32_e32 v26, v27, v26 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 ; VI-NEXT: v_or_b32_e32 v27, v28, v27 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v58, v29 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v30, v29, s4 ; VI-NEXT: v_or_b32_e32 v28, v29, v28 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_mov_b32_e32 v58, v29 +; VI-NEXT: v_mov_b32_e32 v44, v30 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v29, v29, v30, s4 -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v60, v29 +; VI-NEXT: v_perm_b32 v29, v30, v29, s4 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v29, 16, v29 +; VI-NEXT: v_mov_b32_e32 v57, v31 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v31, v30, s4 ; VI-NEXT: v_or_b32_e32 v29, v30, v29 @@ -140981,28 +140980,39 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: v_perm_b32 v31, v50, v36, s4 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 ; VI-NEXT: v_or_b32_e32 v31, v42, v31 -; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v36, v34 ; VI-NEXT: s_cbranch_execnz .LBB89_3 ; VI-NEXT: .LBB89_2: ; %cmp.true -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v32 ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 ; VI-NEXT: v_perm_b32 v0, v0, v41, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v33 +; VI-NEXT: s_waitcnt vmcnt(10) ; VI-NEXT: v_perm_b32 v0, v0, v37, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v36 +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_perm_b32 v0, v0, v38, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v39 +; VI-NEXT: s_waitcnt vmcnt(4) ; VI-NEXT: v_perm_b32 v21, v0, v49, s4 -; VI-NEXT: s_waitcnt vmcnt(5) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 +; VI-NEXT: v_perm_b32 v22, v0, v60, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v57 ; VI-NEXT: v_mov_b32_e32 v34, v35 ; VI-NEXT: s_add_i32 s28, s28, 3 ; VI-NEXT: s_add_i32 s26, s26, 3 @@ -141010,289 +141020,284 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: s_add_i32 s22, s22, 3 ; VI-NEXT: s_add_i32 s20, s20, 3 ; VI-NEXT: s_add_i32 s18, s18, 3 -; VI-NEXT: v_mov_b32_e32 v63, s19 ; VI-NEXT: s_add_i32 s16, s16, 3 ; VI-NEXT: v_mov_b32_e32 v18, s17 ; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: v_perm_b32 v22, v0, v1, s4 -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v60 -; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v24, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v27, vcc, 0x300, v27 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v31, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v33, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v35, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v36, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v37, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v38, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v20, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:836 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v39, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v49, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v50, v0, v47, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v19, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v51, v0, v56, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v32, v0, v55, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v0, v0, v34, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v34, v0, v40, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v10, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:840 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v11, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v13, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v14, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v15, v0, v45, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v15, vcc, 0x300, v15 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v16, v0, v43, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v17, v0, v62, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v48 ; VI-NEXT: v_perm_b32 v55, v0, v42, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v63 +; VI-NEXT: v_perm_b32 v41, v0, v59, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v61 -; VI-NEXT: v_perm_b32 v41, v0, v57, s4 -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 ; VI-NEXT: v_perm_b32 v42, v0, v52, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v54 ; VI-NEXT: v_perm_b32 v43, v0, v53, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v46 +; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v62, s21 -; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v63, s19 +; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v45, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:740 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v45, v0, v59, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v54, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v40, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v9, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v46, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v8, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:708 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:696 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v8, v0, v1, s4 +; VI-NEXT: v_perm_b32 v47, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:700 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:688 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v47, v0, v1, s4 +; VI-NEXT: v_perm_b32 v7, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:692 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:680 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v7, v0, v1, s4 +; VI-NEXT: v_perm_b32 v56, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:684 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:672 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v56, v0, v1, s4 +; VI-NEXT: v_perm_b32 v6, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:676 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:664 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v6, v0, v1, s4 +; VI-NEXT: v_perm_b32 v57, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:668 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:656 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v57, v0, v1, s4 +; VI-NEXT: v_perm_b32 v5, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:660 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:648 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v5, v0, v1, s4 +; VI-NEXT: v_perm_b32 v58, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:652 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:640 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v58, v0, v1, s4 +; VI-NEXT: v_perm_b32 v4, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:644 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:632 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v4, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v59, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) @@ -141457,32 +141462,35 @@ define inreg <64 x bfloat> @bitcast_v128i8_to_v64bf16_scalar(<128 x i8> inreg %a ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: s_setpc_b64 s[30:31] ; VI-NEXT: .LBB89_4: -; VI-NEXT: v_mov_b32_e32 v40, v55 -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v42, v61 -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v63 -; VI-NEXT: v_mov_b32_e32 v45, v34 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v53, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v47, v34 ; VI-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 ; VI-NEXT: ; implicit-def: $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 ; VI-NEXT: s_branch .LBB89_2 @@ -167430,94 +167438,144 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:344 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:340 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:336 ; 4-byte Folded Spill -; VI-NEXT: v_mov_b32_e32 v41, v28 -; VI-NEXT: v_mov_b32_e32 v31, v1 -; VI-NEXT: v_mov_b32_e32 v28, v0 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:332 +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v22, v1 +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:332 ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:8 ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:248 -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v32 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:4 ; VI-NEXT: s_and_b64 s[4:5], vcc, exec -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:244 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:240 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:236 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:224 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:220 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:212 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:204 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:200 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:196 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:292 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:288 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:188 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:184 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:284 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:180 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:280 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:176 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:276 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:172 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:272 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:268 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:164 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:264 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:156 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:152 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:260 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:256 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:252 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:248 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:244 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:240 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:236 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:224 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:220 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:212 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:204 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:200 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:196 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:188 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:184 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:180 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:176 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:172 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:164 +; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:156 +; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:152 ; VI-NEXT: buffer_load_ushort v60, off, s[0:3], s32 offset:148 -; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:144 -; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:140 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:136 +; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:144 +; VI-NEXT: buffer_load_ushort v41, off, s[0:3], s32 offset:140 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:136 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:132 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:128 +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:132 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:128 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v43, off, s[0:3], s32 offset:124 ; VI-NEXT: buffer_load_ushort v45, off, s[0:3], s32 offset:120 ; VI-NEXT: buffer_load_ushort v56, off, s[0:3], s32 offset:116 @@ -167533,223 +167591,158 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: buffer_load_ushort v52, off, s[0:3], s32 offset:76 ; VI-NEXT: buffer_load_ushort v37, off, s[0:3], s32 offset:72 ; VI-NEXT: buffer_load_ushort v50, off, s[0:3], s32 offset:68 -; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:64 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:64 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v48, off, s[0:3], s32 offset:60 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:56 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:56 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v38, off, s[0:3], s32 offset:52 -; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:48 -; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 -; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:40 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:36 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:32 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:28 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:48 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:24 -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:20 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:16 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:12 -; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:40 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:36 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:28 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:24 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:20 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:16 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:292 -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:620 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:288 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:284 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:280 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:276 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:272 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:268 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:12 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:264 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:260 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:256 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:252 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:836 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:840 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill ; VI-NEXT: s_cbranch_scc0 .LBB93_4 ; VI-NEXT: ; %bb.1: ; %cmp.false ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v57, v61 -; VI-NEXT: v_mov_b32_e32 v61, v3 -; VI-NEXT: v_mov_b32_e32 v33, v34 -; VI-NEXT: v_mov_b32_e32 v34, v2 +; VI-NEXT: v_perm_b32 v6, v6, v7, s4 +; VI-NEXT: v_perm_b32 v7, v10, v11, s4 +; VI-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v58, v24 +; VI-NEXT: v_mov_b32_e32 v24, v3 +; VI-NEXT: v_mov_b32_e32 v42, v2 ; VI-NEXT: v_perm_b32 v4, v4, v5, s4 ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 -; VI-NEXT: v_perm_b32 v5, v34, v61, s4 +; VI-NEXT: v_perm_b32 v5, v42, v24, s4 ; VI-NEXT: v_or_b32_e32 v4, v5, v4 ; VI-NEXT: v_perm_b32 v5, v8, v9, s4 ; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 -; VI-NEXT: v_perm_b32 v6, v6, v7, s4 ; VI-NEXT: v_or_b32_e32 v5, v6, v5 ; VI-NEXT: v_perm_b32 v6, v12, v13, s4 ; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 -; VI-NEXT: v_perm_b32 v7, v10, v11, s4 ; VI-NEXT: v_or_b32_e32 v6, v7, v6 ; VI-NEXT: v_perm_b32 v7, v16, v17, s4 +; VI-NEXT: v_mov_b32_e32 v1, s17 +; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 ; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: v_perm_b32 v8, v14, v15, s4 +; VI-NEXT: v_perm_b32 v62, s16, v1, v3 +; VI-NEXT: v_mov_b32_e32 v1, s19 ; VI-NEXT: v_or_b32_e32 v7, v8, v7 ; VI-NEXT: v_perm_b32 v8, v20, v21, s4 +; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: v_perm_b32 v9, v18, v19, s4 +; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_or_b32_e32 v8, v9, v8 -; VI-NEXT: v_perm_b32 v9, v24, v25, s4 +; VI-NEXT: v_perm_b32 v9, v58, v25, s4 +; VI-NEXT: v_mov_b32_e32 v59, v0 +; VI-NEXT: buffer_store_dword v34, off, s[0:3], s32 offset:844 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v34, v28 +; VI-NEXT: v_or_b32_e32 v0, v62, v1 ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 -; VI-NEXT: v_perm_b32 v10, v22, v23, s4 -; VI-NEXT: v_or_b32_e32 v9, v10, v9 -; VI-NEXT: v_perm_b32 v10, v41, v29, s4 -; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v11, v26, v27, s4 -; VI-NEXT: v_or_b32_e32 v10, v11, v10 -; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v17, v35, v53, s4 ; VI-NEXT: v_lshlrev_b32_e32 v17, 16, v17 ; VI-NEXT: v_perm_b32 v19, v40, v51, s4 -; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v16, v48, v33, s4 ; VI-NEXT: v_or_b32_e32 v17, v19, v17 -; VI-NEXT: v_mov_b32_e32 v40, v55 ; VI-NEXT: v_perm_b32 v19, v47, v55, s4 -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v21, v58, v59, s4 -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v32, v62 -; VI-NEXT: v_mov_b32_e32 v62, v28 -; VI-NEXT: v_mov_b32_e32 v28, v31 -; VI-NEXT: v_perm_b32 v28, v62, v28, s4 -; VI-NEXT: v_mov_b32_e32 v62, v63 -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v28, v59, v22, s4 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: v_perm_b32 v21, v41, v46, s4 ; VI-NEXT: v_perm_b32 v18, v52, v39, s4 -; VI-NEXT: v_perm_b32 v15, v36, v32, s4 -; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v1, s19 +; VI-NEXT: v_perm_b32 v22, v32, v44, s4 ; VI-NEXT: v_mov_b32_e32 v31, s23 -; VI-NEXT: v_mov_b32_e32 v0, s17 -; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_mov_b32_e32 v2, s21 ; VI-NEXT: v_perm_b32 v31, s22, v31, v3 -; VI-NEXT: v_perm_b32 v0, s16, v0, v3 -; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_perm_b32 v2, s20, v2, v3 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 -; VI-NEXT: v_or_b32_e32 v0, v0, v1 ; VI-NEXT: v_or_b32_e32 v1, v2, v31 ; VI-NEXT: v_mov_b32_e32 v31, s27 ; VI-NEXT: v_mov_b32_e32 v2, s25 @@ -167761,43 +167754,58 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: v_perm_b32 v3, s28, v31, v3 ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: v_or_b32_e32 v3, v3, v28 +; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v62 -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_perm_b32 v11, v11, v12, s4 +; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:844 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v10, v10, v23, s4 +; VI-NEXT: v_or_b32_e32 v9, v10, v9 +; VI-NEXT: v_perm_b32 v10, v34, v29, s4 +; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: v_or_b32_e32 v10, v11, v10 +; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_mov_b32_e32 v63, v14 -; VI-NEXT: s_waitcnt vmcnt(9) -; VI-NEXT: v_perm_b32 v22, v44, v22, s4 -; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v15, v36, v62, s4 ; VI-NEXT: s_waitcnt vmcnt(4) -; VI-NEXT: v_mov_b32_e32 v43, v41 +; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(3) +; VI-NEXT: v_perm_b32 v16, v48, v16, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v11, v12, v11, s4 +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v30, v12, s4 ; VI-NEXT: v_or_b32_e32 v11, v12, v11 -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v12, v13, v12, s4 +; VI-NEXT: v_perm_b32 v12, v12, v13, s4 +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 -; VI-NEXT: v_perm_b32 v13, v14, v62, s4 +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v53, v61 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v13, v13, v61, s4 ; VI-NEXT: v_or_b32_e32 v12, v13, v12 -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v62, v32 +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v13, v13, v57, s4 -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v13, v13, v14, s4 +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v14, v61, v57, s4 +; VI-NEXT: v_perm_b32 v14, v14, v59, s4 ; VI-NEXT: v_or_b32_e32 v13, v14, v13 -; VI-NEXT: v_perm_b32 v14, v38, v41, s4 +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v14, v38, v14, s4 ; VI-NEXT: v_lshlrev_b32_e32 v14, 16, v14 ; VI-NEXT: v_or_b32_e32 v14, v15, v14 ; VI-NEXT: v_perm_b32 v15, v50, v37, s4 @@ -167807,115 +167815,114 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: v_lshlrev_b32_e32 v16, 16, v16 ; VI-NEXT: v_or_b32_e32 v16, v18, v16 ; VI-NEXT: v_perm_b32 v18, v56, v45, s4 -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 ; VI-NEXT: v_or_b32_e32 v18, v19, v18 -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v54, v63 -; VI-NEXT: v_mov_b32_e32 v45, v33 +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v19, v42, v56, s4 +; VI-NEXT: v_perm_b32 v19, v63, v56, s4 ; VI-NEXT: v_lshlrev_b32_e32 v19, 16, v19 ; VI-NEXT: v_or_b32_e32 v19, v20, v19 ; VI-NEXT: v_perm_b32 v20, v60, v47, s4 ; VI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 ; VI-NEXT: v_or_b32_e32 v20, v21, v20 -; VI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_perm_b32 v21, v33, v57, s4 +; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 +; VI-NEXT: v_or_b32_e32 v21, v22, v21 +; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(2) ; VI-NEXT: v_perm_b32 v42, v51, v37, s4 ; VI-NEXT: v_mov_b32_e32 v41, v36 ; VI-NEXT: v_mov_b32_e32 v32, v50 ; VI-NEXT: v_mov_b32_e32 v33, v51 -; VI-NEXT: v_mov_b32_e32 v60, v31 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v21, v46, v21, s4 -; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 -; VI-NEXT: v_or_b32_e32 v21, v22, v21 -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v22, v23, v22, s4 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v22, 16, v22 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 ; VI-NEXT: v_or_b32_e32 v22, v23, v22 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 ; VI-NEXT: v_or_b32_e32 v23, v24, v23 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v24, 16, v24 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 ; VI-NEXT: v_or_b32_e32 v24, v25, v24 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 ; VI-NEXT: v_or_b32_e32 v25, v26, v25 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 ; VI-NEXT: v_or_b32_e32 v26, v27, v26 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 ; VI-NEXT: v_or_b32_e32 v27, v28, v27 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v58, v29 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v30, v29, s4 ; VI-NEXT: v_or_b32_e32 v28, v29, v28 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_mov_b32_e32 v58, v29 +; VI-NEXT: v_mov_b32_e32 v44, v30 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v29, v29, v30, s4 -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v60, v29 +; VI-NEXT: v_perm_b32 v29, v30, v29, s4 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v29, 16, v29 +; VI-NEXT: v_mov_b32_e32 v57, v31 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v31, v30, s4 ; VI-NEXT: v_or_b32_e32 v29, v30, v29 @@ -167926,28 +167933,39 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: v_perm_b32 v31, v50, v36, s4 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 ; VI-NEXT: v_or_b32_e32 v31, v42, v31 -; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v36, v34 ; VI-NEXT: s_cbranch_execnz .LBB93_3 ; VI-NEXT: .LBB93_2: ; %cmp.true -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v32 ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 ; VI-NEXT: v_perm_b32 v0, v0, v41, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v33 +; VI-NEXT: s_waitcnt vmcnt(10) ; VI-NEXT: v_perm_b32 v0, v0, v37, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v36 +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_perm_b32 v0, v0, v38, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v39 +; VI-NEXT: s_waitcnt vmcnt(4) ; VI-NEXT: v_perm_b32 v21, v0, v49, s4 -; VI-NEXT: s_waitcnt vmcnt(5) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 +; VI-NEXT: v_perm_b32 v22, v0, v60, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v57 ; VI-NEXT: v_mov_b32_e32 v34, v35 ; VI-NEXT: s_add_i32 s28, s28, 3 ; VI-NEXT: s_add_i32 s26, s26, 3 @@ -167955,289 +167973,284 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: s_add_i32 s22, s22, 3 ; VI-NEXT: s_add_i32 s20, s20, 3 ; VI-NEXT: s_add_i32 s18, s18, 3 -; VI-NEXT: v_mov_b32_e32 v63, s19 ; VI-NEXT: s_add_i32 s16, s16, 3 ; VI-NEXT: v_mov_b32_e32 v18, s17 ; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: v_perm_b32 v22, v0, v1, s4 -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v60 -; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v24, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v27, vcc, 0x300, v27 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v31, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v33, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v35, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v36, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v37, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v38, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v20, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:836 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v39, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v49, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v50, v0, v47, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v19, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v51, v0, v56, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v32, v0, v55, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v0, v0, v34, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v34, v0, v40, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v10, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:840 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v11, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v13, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v14, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v15, v0, v45, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v15, vcc, 0x300, v15 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v16, v0, v43, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v17, v0, v62, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v48 ; VI-NEXT: v_perm_b32 v55, v0, v42, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v63 +; VI-NEXT: v_perm_b32 v41, v0, v59, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v61 -; VI-NEXT: v_perm_b32 v41, v0, v57, s4 -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 ; VI-NEXT: v_perm_b32 v42, v0, v52, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v54 ; VI-NEXT: v_perm_b32 v43, v0, v53, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v46 +; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v62, s21 -; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v63, s19 +; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v45, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:740 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v45, v0, v59, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v54, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v40, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v9, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v46, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v8, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:708 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:696 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v8, v0, v1, s4 +; VI-NEXT: v_perm_b32 v47, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:700 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:688 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v47, v0, v1, s4 +; VI-NEXT: v_perm_b32 v7, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:692 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:680 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v7, v0, v1, s4 +; VI-NEXT: v_perm_b32 v56, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:684 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:672 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v56, v0, v1, s4 +; VI-NEXT: v_perm_b32 v6, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:676 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:664 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v6, v0, v1, s4 +; VI-NEXT: v_perm_b32 v57, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:668 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:656 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v57, v0, v1, s4 +; VI-NEXT: v_perm_b32 v5, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:660 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:648 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v5, v0, v1, s4 +; VI-NEXT: v_perm_b32 v58, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:652 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:640 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v58, v0, v1, s4 +; VI-NEXT: v_perm_b32 v4, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:644 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:632 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v4, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v59, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) @@ -168402,32 +168415,35 @@ define inreg <64 x half> @bitcast_v128i8_to_v64f16_scalar(<128 x i8> inreg %a, i ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: s_setpc_b64 s[30:31] ; VI-NEXT: .LBB93_4: -; VI-NEXT: v_mov_b32_e32 v40, v55 -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v42, v61 -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v63 -; VI-NEXT: v_mov_b32_e32 v45, v34 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v53, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v47, v34 ; VI-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 ; VI-NEXT: ; implicit-def: $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 ; VI-NEXT: s_branch .LBB93_2 @@ -188203,94 +188219,144 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:344 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:340 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:336 ; 4-byte Folded Spill -; VI-NEXT: v_mov_b32_e32 v41, v28 -; VI-NEXT: v_mov_b32_e32 v31, v1 -; VI-NEXT: v_mov_b32_e32 v28, v0 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:332 +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v22, v1 +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:332 ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:8 ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:248 -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v32 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:4 ; VI-NEXT: s_and_b64 s[4:5], vcc, exec -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:244 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:240 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:236 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:224 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:220 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:212 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:204 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:200 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:196 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:292 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:288 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:188 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:184 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:284 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:180 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:280 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:176 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:276 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:172 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:272 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:268 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:164 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:484 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:264 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:156 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:152 +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:260 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:584 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:256 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:252 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:248 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:244 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:240 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:236 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:496 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:232 +; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:228 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:224 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:220 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:508 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:216 +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:212 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:208 +; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:204 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:200 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:196 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:192 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:188 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:184 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:444 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:180 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:460 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:176 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:440 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:172 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:452 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v57, off, s[0:3], s32 offset:168 +; VI-NEXT: buffer_load_ushort v33, off, s[0:3], s32 offset:164 +; VI-NEXT: buffer_load_ushort v44, off, s[0:3], s32 offset:160 +; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:156 +; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:152 ; VI-NEXT: buffer_load_ushort v60, off, s[0:3], s32 offset:148 -; VI-NEXT: buffer_load_ushort v59, off, s[0:3], s32 offset:144 -; VI-NEXT: buffer_load_ushort v58, off, s[0:3], s32 offset:140 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:136 +; VI-NEXT: buffer_load_ushort v46, off, s[0:3], s32 offset:144 +; VI-NEXT: buffer_load_ushort v41, off, s[0:3], s32 offset:140 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:136 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:588 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v42, off, s[0:3], s32 offset:132 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:128 +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:132 +; VI-NEXT: buffer_load_ushort v35, off, s[0:3], s32 offset:128 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:592 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v43, off, s[0:3], s32 offset:124 ; VI-NEXT: buffer_load_ushort v45, off, s[0:3], s32 offset:120 ; VI-NEXT: buffer_load_ushort v56, off, s[0:3], s32 offset:116 @@ -188306,223 +188372,158 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: buffer_load_ushort v52, off, s[0:3], s32 offset:76 ; VI-NEXT: buffer_load_ushort v37, off, s[0:3], s32 offset:72 ; VI-NEXT: buffer_load_ushort v50, off, s[0:3], s32 offset:68 -; VI-NEXT: buffer_load_ushort v34, off, s[0:3], s32 offset:64 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:64 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v48, off, s[0:3], s32 offset:60 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:56 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:56 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:596 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill ; VI-NEXT: buffer_load_ushort v38, off, s[0:3], s32 offset:52 -; VI-NEXT: buffer_load_ushort v62, off, s[0:3], s32 offset:48 -; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 -; VI-NEXT: buffer_load_ushort v61, off, s[0:3], s32 offset:40 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:36 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:32 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:28 +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:48 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:24 -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:472 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:20 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:328 -; VI-NEXT: s_waitcnt vmcnt(2) -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v63, off, s[0:3], s32 offset:16 -; VI-NEXT: buffer_load_ushort v0, off, s[0:3], s32 offset:12 -; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:568 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:324 +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:600 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v36, off, s[0:3], s32 offset:44 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:40 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:572 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:320 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:416 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:36 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:316 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:32 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:576 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:312 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:604 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:28 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:308 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:420 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:24 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:580 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:304 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:428 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:20 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:564 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:300 +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:424 ; 4-byte Folded Spill +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:16 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:560 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v1, off, s[0:3], s32 offset:296 -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:292 -; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:616 ; 4-byte Folded Spill ; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:620 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:624 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:456 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:492 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) -; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Spill -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:608 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:288 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:284 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:612 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:280 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:500 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:276 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:272 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:516 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:268 +; VI-NEXT: buffer_load_ushort v31, off, s[0:3], s32 offset:12 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:264 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:520 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:260 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:256 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:524 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_ushort v32, off, s[0:3], s32 offset:252 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:480 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v31, off, s[0:3], s32 offset:432 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v22, off, s[0:3], s32 offset:628 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:632 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:640 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:644 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:648 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:652 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:656 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:660 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:664 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:668 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:672 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:676 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:680 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:684 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:688 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:692 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:696 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:700 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v21, off, s[0:3], s32 offset:704 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:708 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v23, off, s[0:3], s32 offset:712 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:716 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v25, off, s[0:3], s32 offset:720 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v27, off, s[0:3], s32 offset:724 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v24, off, s[0:3], s32 offset:728 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v29, off, s[0:3], s32 offset:732 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v26, off, s[0:3], s32 offset:736 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v28, off, s[0:3], s32 offset:740 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v30, off, s[0:3], s32 offset:744 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v36, off, s[0:3], s32 offset:748 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v37, off, s[0:3], s32 offset:752 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v38, off, s[0:3], s32 offset:756 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v48, off, s[0:3], s32 offset:760 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v49, off, s[0:3], s32 offset:764 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v50, off, s[0:3], s32 offset:768 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v54, off, s[0:3], s32 offset:772 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v40, off, s[0:3], s32 offset:776 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v35, off, s[0:3], s32 offset:780 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v47, off, s[0:3], s32 offset:784 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v56, off, s[0:3], s32 offset:788 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v46, off, s[0:3], s32 offset:792 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v43, off, s[0:3], s32 offset:796 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v63, off, s[0:3], s32 offset:800 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v39, off, s[0:3], s32 offset:804 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v44, off, s[0:3], s32 offset:808 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v41, off, s[0:3], s32 offset:812 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v52, off, s[0:3], s32 offset:816 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v53, off, s[0:3], s32 offset:820 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:824 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v60, off, s[0:3], s32 offset:828 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v32, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v33, off, s[0:3], s32 offset:836 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v51, off, s[0:3], s32 offset:840 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v58, off, s[0:3], s32 offset:448 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v42, off, s[0:3], s32 offset:476 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v62, off, s[0:3], s32 offset:504 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v59, off, s[0:3], s32 offset:544 ; 4-byte Folded Spill +; VI-NEXT: buffer_store_dword v61, off, s[0:3], s32 offset:552 ; 4-byte Folded Spill ; VI-NEXT: s_cbranch_scc0 .LBB97_4 ; VI-NEXT: ; %bb.1: ; %cmp.false ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v57, v61 -; VI-NEXT: v_mov_b32_e32 v61, v3 -; VI-NEXT: v_mov_b32_e32 v33, v34 -; VI-NEXT: v_mov_b32_e32 v34, v2 +; VI-NEXT: v_perm_b32 v6, v6, v7, s4 +; VI-NEXT: v_perm_b32 v7, v10, v11, s4 +; VI-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v58, v24 +; VI-NEXT: v_mov_b32_e32 v24, v3 +; VI-NEXT: v_mov_b32_e32 v42, v2 ; VI-NEXT: v_perm_b32 v4, v4, v5, s4 ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 -; VI-NEXT: v_perm_b32 v5, v34, v61, s4 +; VI-NEXT: v_perm_b32 v5, v42, v24, s4 ; VI-NEXT: v_or_b32_e32 v4, v5, v4 ; VI-NEXT: v_perm_b32 v5, v8, v9, s4 ; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 -; VI-NEXT: v_perm_b32 v6, v6, v7, s4 ; VI-NEXT: v_or_b32_e32 v5, v6, v5 ; VI-NEXT: v_perm_b32 v6, v12, v13, s4 ; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 -; VI-NEXT: v_perm_b32 v7, v10, v11, s4 ; VI-NEXT: v_or_b32_e32 v6, v7, v6 ; VI-NEXT: v_perm_b32 v7, v16, v17, s4 +; VI-NEXT: v_mov_b32_e32 v1, s17 +; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 ; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: v_perm_b32 v8, v14, v15, s4 +; VI-NEXT: v_perm_b32 v62, s16, v1, v3 +; VI-NEXT: v_mov_b32_e32 v1, s19 ; VI-NEXT: v_or_b32_e32 v7, v8, v7 ; VI-NEXT: v_perm_b32 v8, v20, v21, s4 +; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: v_perm_b32 v9, v18, v19, s4 +; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_or_b32_e32 v8, v9, v8 -; VI-NEXT: v_perm_b32 v9, v24, v25, s4 +; VI-NEXT: v_perm_b32 v9, v58, v25, s4 +; VI-NEXT: v_mov_b32_e32 v59, v0 +; VI-NEXT: buffer_store_dword v34, off, s[0:3], s32 offset:844 ; 4-byte Folded Spill +; VI-NEXT: v_mov_b32_e32 v34, v28 +; VI-NEXT: v_or_b32_e32 v0, v62, v1 ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 -; VI-NEXT: v_perm_b32 v10, v22, v23, s4 -; VI-NEXT: v_or_b32_e32 v9, v10, v9 -; VI-NEXT: v_perm_b32 v10, v41, v29, s4 -; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v11, v26, v27, s4 -; VI-NEXT: v_or_b32_e32 v10, v11, v10 -; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload ; VI-NEXT: v_perm_b32 v17, v35, v53, s4 ; VI-NEXT: v_lshlrev_b32_e32 v17, 16, v17 ; VI-NEXT: v_perm_b32 v19, v40, v51, s4 -; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v16, v48, v33, s4 ; VI-NEXT: v_or_b32_e32 v17, v19, v17 -; VI-NEXT: v_mov_b32_e32 v40, v55 ; VI-NEXT: v_perm_b32 v19, v47, v55, s4 -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_perm_b32 v21, v58, v59, s4 -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v32, v62 -; VI-NEXT: v_mov_b32_e32 v62, v28 -; VI-NEXT: v_mov_b32_e32 v28, v31 -; VI-NEXT: v_perm_b32 v28, v62, v28, s4 -; VI-NEXT: v_mov_b32_e32 v62, v63 -; VI-NEXT: buffer_store_dword v57, off, s[0:3], s32 offset:832 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v28, v59, v22, s4 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: v_perm_b32 v21, v41, v46, s4 ; VI-NEXT: v_perm_b32 v18, v52, v39, s4 -; VI-NEXT: v_perm_b32 v15, v36, v32, s4 -; VI-NEXT: v_mov_b32_e32 v3, 0xc0c0004 -; VI-NEXT: v_mov_b32_e32 v1, s19 +; VI-NEXT: v_perm_b32 v22, v32, v44, s4 ; VI-NEXT: v_mov_b32_e32 v31, s23 -; VI-NEXT: v_mov_b32_e32 v0, s17 -; VI-NEXT: v_perm_b32 v1, s18, v1, v3 ; VI-NEXT: v_mov_b32_e32 v2, s21 ; VI-NEXT: v_perm_b32 v31, s22, v31, v3 -; VI-NEXT: v_perm_b32 v0, s16, v0, v3 -; VI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; VI-NEXT: v_perm_b32 v2, s20, v2, v3 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 -; VI-NEXT: v_or_b32_e32 v0, v0, v1 ; VI-NEXT: v_or_b32_e32 v1, v2, v31 ; VI-NEXT: v_mov_b32_e32 v31, s27 ; VI-NEXT: v_mov_b32_e32 v2, s25 @@ -188534,43 +188535,58 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: v_perm_b32 v3, s28, v31, v3 ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: v_or_b32_e32 v3, v3, v28 +; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v62 -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_perm_b32 v11, v11, v12, s4 +; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:844 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v10, v10, v23, s4 +; VI-NEXT: v_or_b32_e32 v9, v10, v9 +; VI-NEXT: v_perm_b32 v10, v34, v29, s4 +; VI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 +; VI-NEXT: v_or_b32_e32 v10, v11, v10 +; VI-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 -; VI-NEXT: s_waitcnt vmcnt(10) -; VI-NEXT: v_mov_b32_e32 v63, v14 -; VI-NEXT: s_waitcnt vmcnt(9) -; VI-NEXT: v_perm_b32 v22, v44, v22, s4 -; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(7) +; VI-NEXT: v_perm_b32 v15, v36, v62, s4 ; VI-NEXT: s_waitcnt vmcnt(4) -; VI-NEXT: v_mov_b32_e32 v43, v41 +; VI-NEXT: v_perm_b32 v20, v43, v55, s4 +; VI-NEXT: s_waitcnt vmcnt(3) +; VI-NEXT: v_perm_b32 v16, v48, v16, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v11, v12, v11, s4 +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v30, v12, s4 ; VI-NEXT: v_or_b32_e32 v11, v12, v11 -; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v12, v13, v12, s4 +; VI-NEXT: v_perm_b32 v12, v12, v13, s4 +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 -; VI-NEXT: v_perm_b32 v13, v14, v62, s4 +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v53, v61 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v13, v13, v61, s4 ; VI-NEXT: v_or_b32_e32 v12, v13, v12 -; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v62, v32 +; VI-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v13, v13, v57, s4 -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v13, v13, v14, s4 +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v13, 16, v13 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v14, v61, v57, s4 +; VI-NEXT: v_perm_b32 v14, v14, v59, s4 ; VI-NEXT: v_or_b32_e32 v13, v14, v13 -; VI-NEXT: v_perm_b32 v14, v38, v41, s4 +; VI-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v14, v38, v14, s4 ; VI-NEXT: v_lshlrev_b32_e32 v14, 16, v14 ; VI-NEXT: v_or_b32_e32 v14, v15, v14 ; VI-NEXT: v_perm_b32 v15, v50, v37, s4 @@ -188580,115 +188596,114 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: v_lshlrev_b32_e32 v16, 16, v16 ; VI-NEXT: v_or_b32_e32 v16, v18, v16 ; VI-NEXT: v_perm_b32 v18, v56, v45, s4 -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 ; VI-NEXT: v_or_b32_e32 v18, v19, v18 -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v54, v63 -; VI-NEXT: v_mov_b32_e32 v45, v33 +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v50, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v51, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(8) -; VI-NEXT: v_perm_b32 v19, v42, v56, s4 +; VI-NEXT: v_perm_b32 v19, v63, v56, s4 ; VI-NEXT: v_lshlrev_b32_e32 v19, 16, v19 ; VI-NEXT: v_or_b32_e32 v19, v20, v19 ; VI-NEXT: v_perm_b32 v20, v60, v47, s4 ; VI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 ; VI-NEXT: v_or_b32_e32 v20, v21, v20 -; VI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_perm_b32 v21, v33, v57, s4 +; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 +; VI-NEXT: v_or_b32_e32 v21, v22, v21 +; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(2) ; VI-NEXT: v_perm_b32 v42, v51, v37, s4 ; VI-NEXT: v_mov_b32_e32 v41, v36 ; VI-NEXT: v_mov_b32_e32 v32, v50 ; VI-NEXT: v_mov_b32_e32 v33, v51 -; VI-NEXT: v_mov_b32_e32 v60, v31 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v21, v46, v21, s4 -; VI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 -; VI-NEXT: v_or_b32_e32 v21, v22, v21 -; VI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v22, v23, v22, s4 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v22, 16, v22 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 ; VI-NEXT: v_or_b32_e32 v22, v23, v22 -; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v24, v23, s4 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 ; VI-NEXT: v_or_b32_e32 v23, v24, v23 -; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v24, v25, v24, s4 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: v_perm_b32 v24, v24, v25, s4 +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v24, 16, v24 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 ; VI-NEXT: v_or_b32_e32 v24, v25, v24 -; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v26, v25, s4 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 ; VI-NEXT: v_or_b32_e32 v25, v26, v25 -; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v27, v26, s4 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 ; VI-NEXT: v_or_b32_e32 v26, v27, v26 -; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v28, v27, s4 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 ; VI-NEXT: v_or_b32_e32 v27, v28, v27 -; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_mov_b32_e32 v58, v29 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v29, v28, s4 -; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v30, v29, s4 ; VI-NEXT: v_or_b32_e32 v28, v29, v28 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_mov_b32_e32 v58, v29 +; VI-NEXT: v_mov_b32_e32 v44, v30 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v29, v29, v30, s4 -; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v60, v29 +; VI-NEXT: v_perm_b32 v29, v30, v29, s4 +; VI-NEXT: buffer_load_dword v30, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v29, 16, v29 +; VI-NEXT: v_mov_b32_e32 v57, v31 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v31, v30, s4 ; VI-NEXT: v_or_b32_e32 v29, v30, v29 @@ -188699,28 +188714,39 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: v_perm_b32 v31, v50, v36, s4 ; VI-NEXT: v_lshlrev_b32_e32 v31, 16, v31 ; VI-NEXT: v_or_b32_e32 v31, v42, v31 -; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v36, v34 ; VI-NEXT: s_cbranch_execnz .LBB97_3 ; VI-NEXT: .LBB97_2: ; %cmp.true -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v32 ; VI-NEXT: s_mov_b32 s4, 0xc0c0004 ; VI-NEXT: v_perm_b32 v0, v0, v41, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:400 ; 4-byte Folded Spill +; VI-NEXT: s_waitcnt vmcnt(13) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v33 +; VI-NEXT: s_waitcnt vmcnt(10) ; VI-NEXT: v_perm_b32 v0, v0, v37, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:404 ; 4-byte Folded Spill ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v36 +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_perm_b32 v0, v0, v38, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:408 ; 4-byte Folded Spill -; VI-NEXT: s_waitcnt vmcnt(14) +; VI-NEXT: s_waitcnt vmcnt(9) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v39 +; VI-NEXT: s_waitcnt vmcnt(4) ; VI-NEXT: v_perm_b32 v21, v0, v49, s4 -; VI-NEXT: s_waitcnt vmcnt(5) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 +; VI-NEXT: v_perm_b32 v22, v0, v60, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v57 ; VI-NEXT: v_mov_b32_e32 v34, v35 ; VI-NEXT: s_add_i32 s28, s28, 3 ; VI-NEXT: s_add_i32 s26, s26, 3 @@ -188728,289 +188754,284 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: s_add_i32 s22, s22, 3 ; VI-NEXT: s_add_i32 s20, s20, 3 ; VI-NEXT: s_add_i32 s18, s18, 3 -; VI-NEXT: v_mov_b32_e32 v63, s19 ; VI-NEXT: s_add_i32 s16, s16, 3 ; VI-NEXT: v_mov_b32_e32 v18, s17 ; VI-NEXT: s_waitcnt vmcnt(3) -; VI-NEXT: v_perm_b32 v22, v0, v1, s4 -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v60 -; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v23, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v58 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v24, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v25, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:516 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v26, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v27, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:520 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v27, vcc, 0x300, v27 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v28, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:484 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:528 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v29, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:540 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:532 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:544 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v30, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:496 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:488 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:508 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:500 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v31, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:536 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:548 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:476 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v33, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:492 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:504 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:468 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v35, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:464 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:480 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v36, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:456 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:448 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v37, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:460 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:444 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v38, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:452 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:440 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v20, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:836 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:824 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v39, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:832 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v49, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v50, v0, v47, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v19, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:812 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:820 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v51, v0, v56, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:792 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:796 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v32, v0, v55, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:788 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v0, v0, v34, s4 ; VI-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:412 ; 4-byte Folded Spill -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:784 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v34, v0, v40, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:780 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v10, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:828 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:776 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:840 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v11, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:772 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v12, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:808 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:800 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:816 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:804 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v13, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:764 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:768 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v14, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:512 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:760 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:524 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v15, v0, v45, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:752 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:756 ; 4-byte Folded Reload ; VI-NEXT: v_add_u32_e32 v15, vcc, 0x300, v15 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v16, v0, v43, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:748 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v17, v0, v62, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v48 ; VI-NEXT: v_perm_b32 v55, v0, v42, s4 +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v63 +; VI-NEXT: v_perm_b32 v41, v0, v59, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v61 -; VI-NEXT: v_perm_b32 v41, v0, v57, s4 -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v44 ; VI-NEXT: v_perm_b32 v42, v0, v52, s4 ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v54 ; VI-NEXT: v_perm_b32 v43, v0, v53, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:472 ; 4-byte Folded Reload +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v46 +; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:744 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v62, s21 -; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_mov_b32_e32 v63, s19 +; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v44, v0, v1, s4 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v45, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:740 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: v_perm_b32 v45, v0, v59, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: v_perm_b32 v54, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:732 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:736 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v40, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:724 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:728 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:720 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v9, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:436 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:712 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v9, 16, v9 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v46, v0, v1, s4 +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:716 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:704 ; 4-byte Folded Reload +; VI-NEXT: s_waitcnt vmcnt(1) +; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 +; VI-NEXT: s_waitcnt vmcnt(0) +; VI-NEXT: v_perm_b32 v8, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:708 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:696 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v8, v0, v1, s4 +; VI-NEXT: v_perm_b32 v47, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:700 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:688 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v47, v0, v1, s4 +; VI-NEXT: v_perm_b32 v7, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:692 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:680 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v7, v0, v1, s4 +; VI-NEXT: v_perm_b32 v56, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:684 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:672 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v56, v0, v1, s4 +; VI-NEXT: v_perm_b32 v6, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:676 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:664 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v6, v0, v1, s4 +; VI-NEXT: v_perm_b32 v57, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:668 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:656 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v57, v0, v1, s4 +; VI-NEXT: v_perm_b32 v5, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:660 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:648 ; 4-byte Folded Reload +; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v5, v0, v1, s4 +; VI-NEXT: v_perm_b32 v58, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:652 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:640 ; 4-byte Folded Reload -; VI-NEXT: v_lshlrev_b32_e32 v5, 16, v5 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v58, v0, v1, s4 +; VI-NEXT: v_perm_b32 v4, v0, v1, s4 ; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:644 ; 4-byte Folded Reload ; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:632 ; 4-byte Folded Reload -; VI-NEXT: s_waitcnt vmcnt(1) -; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 -; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_perm_b32 v4, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload ; VI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: v_perm_b32 v59, v0, v1, s4 -; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:636 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:628 ; 4-byte Folded Reload ; VI-NEXT: s_waitcnt vmcnt(1) ; VI-NEXT: v_add_u32_e32 v0, vcc, 3, v0 ; VI-NEXT: s_waitcnt vmcnt(0) @@ -189175,32 +189196,35 @@ define inreg <64 x i16> @bitcast_v128i8_to_v64i16_scalar(<128 x i8> inreg %a, i3 ; VI-NEXT: s_waitcnt vmcnt(0) ; VI-NEXT: s_setpc_b64 s[30:31] ; VI-NEXT: .LBB97_4: -; VI-NEXT: v_mov_b32_e32 v40, v55 -; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:552 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:556 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v47, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload -; VI-NEXT: v_mov_b32_e32 v42, v61 -; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload -; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload ; VI-NEXT: v_mov_b32_e32 v35, v45 -; VI-NEXT: v_mov_b32_e32 v53, v63 -; VI-NEXT: v_mov_b32_e32 v45, v34 +; VI-NEXT: v_mov_b32_e32 v40, v55 +; VI-NEXT: buffer_load_dword v46, off, s[0:3], s32 offset:400 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v53, off, s[0:3], s32 offset:620 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v52, off, s[0:3], s32 offset:428 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v59, off, s[0:3], s32 offset:604 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v54, off, s[0:3], s32 offset:432 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v42, off, s[0:3], s32 offset:416 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v61, off, s[0:3], s32 offset:424 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v62, off, s[0:3], s32 offset:600 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v63, off, s[0:3], s32 offset:420 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v43, off, s[0:3], s32 offset:408 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v48, off, s[0:3], s32 offset:412 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v45, off, s[0:3], s32 offset:404 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v41, off, s[0:3], s32 offset:576 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:580 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:584 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v36, off, s[0:3], s32 offset:588 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v55, off, s[0:3], s32 offset:596 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v37, off, s[0:3], s32 offset:560 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v56, off, s[0:3], s32 offset:592 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v38, off, s[0:3], s32 offset:564 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v39, off, s[0:3], s32 offset:568 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v58, off, s[0:3], s32 offset:624 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v57, off, s[0:3], s32 offset:616 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v60, off, s[0:3], s32 offset:608 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v44, off, s[0:3], s32 offset:612 ; 4-byte Folded Reload +; VI-NEXT: buffer_load_dword v49, off, s[0:3], s32 offset:572 ; 4-byte Folded Reload +; VI-NEXT: v_mov_b32_e32 v47, v34 ; VI-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 ; VI-NEXT: ; implicit-def: $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 ; VI-NEXT: s_branch .LBB97_2 diff --git a/llvm/test/CodeGen/AMDGPU/remat-sop.mir b/llvm/test/CodeGen/AMDGPU/remat-sop.mir index cb652db425421..a1754e4cf3917 100644 --- a/llvm/test/CodeGen/AMDGPU/remat-sop.mir +++ b/llvm/test/CodeGen/AMDGPU/remat-sop.mir @@ -615,9 +615,9 @@ body: | ; GCN-NEXT: renamable $sgpr1 = COPY killed renamable $sgpr3 ; GCN-NEXT: SI_SPILL_S32_SAVE killed renamable $sgpr1, %stack.2, implicit $exec, implicit $sp_reg :: (store (s32) into %stack.2, addrspace 5) ; GCN-NEXT: renamable $sgpr0_sgpr1 = S_GETPC_B64_pseudo - ; GCN-NEXT: SI_SPILL_S32_SAVE killed renamable $sgpr0, %stack.5, implicit $exec, implicit $sp_reg :: (store (s32) into %stack.5, addrspace 5) - ; GCN-NEXT: renamable $sgpr0 = COPY killed renamable $sgpr1 ; GCN-NEXT: SI_SPILL_S32_SAVE killed renamable $sgpr0, %stack.4, implicit $exec, implicit $sp_reg :: (store (s32) into %stack.4, addrspace 5) + ; GCN-NEXT: renamable $sgpr0 = COPY killed renamable $sgpr1 + ; GCN-NEXT: SI_SPILL_S32_SAVE killed renamable $sgpr0, %stack.5, implicit $exec, implicit $sp_reg :: (store (s32) into %stack.5, addrspace 5) ; GCN-NEXT: renamable $sgpr0 = SI_SPILL_S32_RESTORE %stack.1, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.1, addrspace 5) ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.3, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.3, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADD_U32 killed renamable $sgpr1, killed renamable $sgpr0, implicit-def $scc @@ -625,16 +625,16 @@ body: | ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.2, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.2, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADDC_U32 killed renamable $sgpr0, killed renamable $sgpr1, implicit-def $scc, implicit $scc ; GCN-NEXT: renamable $sgpr0 = SI_SPILL_S32_RESTORE %stack.3, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.3, addrspace 5) - ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.5, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.5, addrspace 5) + ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.4, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.4, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADD_U32 killed renamable $sgpr0, killed renamable $sgpr1, implicit-def $scc ; GCN-NEXT: renamable $sgpr0 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.0, addrspace 5) - ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.4, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.4, addrspace 5) + ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.5, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.5, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADDC_U32 killed renamable $sgpr0, killed renamable $sgpr1, implicit-def $scc, implicit $scc ; GCN-NEXT: renamable $sgpr0 = SI_SPILL_S32_RESTORE %stack.1, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.1, addrspace 5) - ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.5, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.5, addrspace 5) + ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.4, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.4, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADD_U32 killed renamable $sgpr0, killed renamable $sgpr1, implicit-def $scc ; GCN-NEXT: renamable $sgpr0 = SI_SPILL_S32_RESTORE %stack.2, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.2, addrspace 5) - ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.4, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.4, addrspace 5) + ; GCN-NEXT: renamable $sgpr1 = SI_SPILL_S32_RESTORE %stack.5, implicit $exec, implicit $sp_reg :: (load (s32) from %stack.5, addrspace 5) ; GCN-NEXT: dead renamable $sgpr0 = S_ADDC_U32 killed renamable $sgpr0, killed renamable $sgpr1, implicit-def $scc, implicit $scc ; GCN-NEXT: S_ENDPGM 0 %0:sreg_64 = S_GETPC_B64_pseudo diff --git a/llvm/test/CodeGen/X86/statepoint-live-in.ll b/llvm/test/CodeGen/X86/statepoint-live-in.ll index 787a33aa49b20..9cf647f8100cd 100644 --- a/llvm/test/CodeGen/X86/statepoint-live-in.ll +++ b/llvm/test/CodeGen/X86/statepoint-live-in.ll @@ -372,8 +372,8 @@ define void @test10(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 ; CHECK-NEXT: .cfi_offset %r14, -32 ; CHECK-NEXT: .cfi_offset %r15, -24 ; CHECK-NEXT: .cfi_offset %rbp, -16 -; CHECK-NEXT: movl %r9d, %ebp -; CHECK-NEXT: movl %r8d, %ebx +; CHECK-NEXT: movl %r9d, %ebx +; CHECK-NEXT: movl %r8d, %ebp ; CHECK-NEXT: movl %ecx, %r14d ; CHECK-NEXT: movl %edx, %r15d ; CHECK-NEXT: movl %esi, %r12d diff --git a/llvm/test/CodeGen/X86/statepoint-regs.ll b/llvm/test/CodeGen/X86/statepoint-regs.ll index 5c26e29dce45e..cbbdae1616fe8 100644 --- a/llvm/test/CodeGen/X86/statepoint-regs.ll +++ b/llvm/test/CodeGen/X86/statepoint-regs.ll @@ -484,8 +484,8 @@ define void @test10(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 ; CHECK-NEXT: .cfi_offset %r14, -32 ; CHECK-NEXT: .cfi_offset %r15, -24 ; CHECK-NEXT: .cfi_offset %rbp, -16 -; CHECK-NEXT: movl %r9d, %ebp -; CHECK-NEXT: movl %r8d, %ebx +; CHECK-NEXT: movl %r9d, %ebx +; CHECK-NEXT: movl %r8d, %ebp ; CHECK-NEXT: movl %ecx, %r14d ; CHECK-NEXT: movl %edx, %r15d ; CHECK-NEXT: movl %esi, %r12d From 282a2b77c358c4509f8fcc97c2f0f2b8cdc9b915 Mon Sep 17 00:00:00 2001 From: Aviral Goel Date: Fri, 27 Feb 2026 11:00:09 -0800 Subject: [PATCH 30/58] [clang][ssaf] Add `JSONFormat` support for `TUSummaryEncoding` This PR adds `JSONFormat` support for reading and writing `TUSummaryEncoding`. The implementation exploits similarities in the structures of `TUSummary` and `TUSummaryEncoding` by reusing existing `JSONFormat` support for `TUSummary`. Duplication of tests has been avoided by parameterizing the test fixture that runs all relevant read/write tests against `TUSummary`, for `TUSummaryEncoding`. This ensures that the two serialization paths remain in lockstep. --- .../Scalable/Serialization/JSONFormat.h | 37 +- .../Serialization/SerializationFormat.h | 7 + clang/lib/Analysis/Scalable/CMakeLists.txt | 4 +- .../Scalable/Serialization/JSONFormat.cpp | 1182 ----------------- .../JSONFormat/JSONFormatImpl.cpp | 596 +++++++++ .../Serialization/JSONFormat/JSONFormatImpl.h | 148 +++ .../Serialization/JSONFormat/TUSummary.cpp | 504 +++++++ .../JSONFormat/TUSummaryEncoding.cpp | 407 ++++++ .../Registries/MockSerializationFormat.cpp | 13 + .../Registries/MockSerializationFormat.h | 6 + .../JSONFormatTest/TUSummaryTest.cpp | 1088 ++++++++------- 11 files changed, 2332 insertions(+), 1660 deletions(-) delete mode 100644 clang/lib/Analysis/Scalable/Serialization/JSONFormat.cpp create mode 100644 clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.cpp create mode 100644 clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.h create mode 100644 clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummary.cpp create mode 100644 clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummaryEncoding.cpp diff --git a/clang/include/clang/Analysis/Scalable/Serialization/JSONFormat.h b/clang/include/clang/Analysis/Scalable/Serialization/JSONFormat.h index 30dfa305238f6..f69dfd6444685 100644 --- a/clang/include/clang/Analysis/Scalable/Serialization/JSONFormat.h +++ b/clang/include/clang/Analysis/Scalable/Serialization/JSONFormat.h @@ -54,6 +54,12 @@ class JSONFormat final : public SerializationFormat { llvm::Error writeTUSummary(const TUSummary &Summary, llvm::StringRef Path) override; + llvm::Expected + readTUSummaryEncoding(llvm::StringRef Path) override; + + llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, + llvm::StringRef Path) override; + using SerializerFn = llvm::function_ref; using DeserializerFn = @@ -98,7 +104,7 @@ class JSONFormat final : public SerializationFormat { llvm::Expected> linkageTableFromJSON(const Array &LinkageTableArray, - std::set EntityIds) const; + std::set ExpectedIds) const; Array linkageTableToJSON( const std::map &LinkageTable) const; @@ -141,6 +147,35 @@ class JSONFormat final : public SerializationFormat { const std::map>> &SummaryDataMap) const; + + llvm::Expected>> + encodingDataMapEntryFromJSON(const Object &EntityDataMapEntryObject) const; + Object encodingDataMapEntryToJSON( + EntityId EI, + const std::unique_ptr &Encoding) const; + + llvm::Expected>> + encodingDataMapFromJSON(const Array &EntityDataArray) const; + Array encodingDataMapToJSON( + const std::map> + &EncodingDataMap) const; + + llvm::Expected>>> + encodingSummaryDataMapEntryFromJSON( + const Object &SummaryDataMapEntryObject) const; + Object encodingSummaryDataMapEntryToJSON( + const SummaryName &SN, + const std::map> + &EncodingMap) const; + + llvm::Expected>>> + encodingSummaryDataMapFromJSON(const Array &SummaryDataArray) const; + Array encodingSummaryDataMapToJSON( + const std::map>> + &EncodingSummaryDataMap) const; }; } // namespace clang::ssaf diff --git a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h index 622e3610bfc8e..784e239f4d7a8 100644 --- a/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h +++ b/clang/include/clang/Analysis/Scalable/Serialization/SerializationFormat.h @@ -35,6 +35,13 @@ class SerializationFormat { virtual llvm::Error writeTUSummary(const TUSummary &Summary, llvm::StringRef Path) = 0; + virtual llvm::Expected + readTUSummaryEncoding(llvm::StringRef Path) = 0; + + virtual llvm::Error + writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, + llvm::StringRef Path) = 0; + protected: // Helpers providing access to implementation details of basic data structures // for efficient serialization/deserialization. diff --git a/clang/lib/Analysis/Scalable/CMakeLists.txt b/clang/lib/Analysis/Scalable/CMakeLists.txt index 28beabb503a17..5d195174d9f9d 100644 --- a/clang/lib/Analysis/Scalable/CMakeLists.txt +++ b/clang/lib/Analysis/Scalable/CMakeLists.txt @@ -11,7 +11,9 @@ add_clang_library(clangAnalysisScalable Model/EntityLinkage.cpp Model/EntityName.cpp Model/SummaryName.cpp - Serialization/JSONFormat.cpp + Serialization/JSONFormat/JSONFormatImpl.cpp + Serialization/JSONFormat/TUSummary.cpp + Serialization/JSONFormat/TUSummaryEncoding.cpp Serialization/SerializationFormatRegistry.cpp Support/ErrorBuilder.cpp TUSummary/ExtractorRegistry.cpp diff --git a/clang/lib/Analysis/Scalable/Serialization/JSONFormat.cpp b/clang/lib/Analysis/Scalable/Serialization/JSONFormat.cpp deleted file mode 100644 index 02c3b9b51da3e..0000000000000 --- a/clang/lib/Analysis/Scalable/Serialization/JSONFormat.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -#include "clang/Analysis/Scalable/Serialization/JSONFormat.h" - -#include "../ModelStringConversions.h" - -#include "clang/Analysis/Scalable/Model/EntityLinkage.h" -#include "clang/Analysis/Scalable/Support/ErrorBuilder.h" -#include "clang/Analysis/Scalable/Support/FormatProviders.h" -#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/JSON.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Registry.h" - -using namespace clang::ssaf; - -using Array = llvm::json::Array; -using Object = llvm::json::Object; -using Value = llvm::json::Value; - -LLVM_INSTANTIATE_REGISTRY(llvm::Registry) - -//---------------------------------------------------------------------------- -// File Format Constant -//---------------------------------------------------------------------------- - -namespace { - -constexpr const char *JSONFormatFileExtension = ".json"; - -} - -//---------------------------------------------------------------------------- -// Error Message Constants -//---------------------------------------------------------------------------- - -namespace { - -namespace ErrorMessages { - -constexpr const char *FailedToReadFile = "failed to read file '{0}': {1}"; -constexpr const char *FailedToWriteFile = "failed to write file '{0}': {1}"; -constexpr const char *FileNotFound = "file does not exist"; -constexpr const char *FileIsDirectory = "path is a directory, not a file"; -constexpr const char *FileIsNotJSON = "file does not end with '{0}' extension"; -constexpr const char *FileExists = "file already exists"; -constexpr const char *ParentDirectoryNotFound = - "parent directory does not exist"; - -constexpr const char *ReadingFromField = "reading {0} from field '{1}'"; -constexpr const char *WritingToField = "writing {0} to field '{1}'"; -constexpr const char *ReadingFromIndex = "reading {0} from index '{1}'"; -constexpr const char *WritingToIndex = "writing {0} to index '{1}'"; -constexpr const char *ReadingFromFile = "reading {0} from file '{1}'"; -constexpr const char *WritingToFile = "writing {0} to file '{1}'"; - -constexpr const char *FailedInsertionOnDuplication = - "failed to insert {0} at index '{1}': encountered duplicate '{2}'"; - -constexpr const char *FailedToReadObject = - "failed to read {0}: expected JSON {1}"; -constexpr const char *FailedToReadObjectAtField = - "failed to read {0} from field '{1}': expected JSON {2}"; -constexpr const char *FailedToReadObjectAtIndex = - "failed to read {0} from index '{1}': expected JSON {2}"; - -constexpr const char *FailedToDeserializeEntitySummaryNoFormatInfo = - "failed to deserialize EntitySummary: no FormatInfo registered for '{0}'"; -constexpr const char *FailedToSerializeEntitySummaryNoFormatInfo = - "failed to serialize EntitySummary: no FormatInfo registered for '{0}'"; - -constexpr const char *FailedToDeserializeEntitySummaryMissingData = - "failed to deserialize EntitySummary: null EntitySummary data for '{0}'"; -constexpr const char *FailedToSerializeEntitySummaryMissingData = - "JSONFormat - null EntitySummary data for '{0}'"; - -constexpr const char *FailedToDeserializeEntitySummaryMismatchedSummaryName = - "failed to deserialize EntitySummary: EntitySummary data for '{0}' reports " - "mismatched '{1}'"; -constexpr const char *FailedToSerializeEntitySummaryMismatchedSummaryName = - "JSONFormat - EntitySummary data for '{0}' reports mismatched '{1}'"; - -constexpr const char *InvalidBuildNamespaceKind = - "invalid 'kind' BuildNamespaceKind value '{0}'"; - -constexpr const char *InvalidEntityLinkageType = - "invalid 'type' EntityLinkageType value '{0}'"; - -constexpr const char *FailedToDeserializeLinkageTableExtraId = - "failed to deserialize LinkageTable: extra '{0}' not present in IdTable"; - -constexpr const char *FailedToDeserializeLinkageTableMissingId = - "failed to deserialize LinkageTable: missing '{0}' present in IdTable"; - -} // namespace ErrorMessages - -} // namespace - -//---------------------------------------------------------------------------- -// JSON Reader and Writer -//---------------------------------------------------------------------------- - -namespace { - -llvm::Expected readJSON(llvm::StringRef Path) { - if (!llvm::sys::fs::exists(Path)) { - return ErrorBuilder::create(std::errc::no_such_file_or_directory, - ErrorMessages::FailedToReadFile, Path, - ErrorMessages::FileNotFound) - .build(); - } - - if (llvm::sys::fs::is_directory(Path)) { - return ErrorBuilder::create(std::errc::is_a_directory, - ErrorMessages::FailedToReadFile, Path, - ErrorMessages::FileIsDirectory) - .build(); - } - - if (!Path.ends_with_insensitive(JSONFormatFileExtension)) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadFile, Path, - llvm::formatv(ErrorMessages::FileIsNotJSON, - JSONFormatFileExtension)) - .build(); - } - - auto BufferOrError = llvm::MemoryBuffer::getFile(Path); - if (!BufferOrError) { - const std::error_code EC = BufferOrError.getError(); - return ErrorBuilder::create(EC, ErrorMessages::FailedToReadFile, Path, - EC.message()) - .build(); - } - - return llvm::json::parse(BufferOrError.get()->getBuffer()); -} - -llvm::Error writeJSON(Value &&Value, llvm::StringRef Path) { - if (llvm::sys::fs::exists(Path)) { - return ErrorBuilder::create(std::errc::file_exists, - ErrorMessages::FailedToWriteFile, Path, - ErrorMessages::FileExists) - .build(); - } - - llvm::StringRef Dir = llvm::sys::path::parent_path(Path); - if (!Dir.empty() && !llvm::sys::fs::is_directory(Dir)) { - return ErrorBuilder::create(std::errc::no_such_file_or_directory, - ErrorMessages::FailedToWriteFile, Path, - ErrorMessages::ParentDirectoryNotFound) - .build(); - } - - if (!Path.ends_with_insensitive(JSONFormatFileExtension)) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToWriteFile, Path, - llvm::formatv(ErrorMessages::FileIsNotJSON, - JSONFormatFileExtension)) - .build(); - } - - std::error_code EC; - llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text); - - if (EC) { - return ErrorBuilder::create(EC, ErrorMessages::FailedToWriteFile, Path, - EC.message()) - .build(); - } - - OutStream << llvm::formatv("{0:2}\n", Value); - OutStream.flush(); - - if (OutStream.has_error()) { - return ErrorBuilder::create(OutStream.error(), - ErrorMessages::FailedToWriteFile, Path, - OutStream.error().message()) - .build(); - } - - return llvm::Error::success(); -} - -} // namespace - -//---------------------------------------------------------------------------- -// JSONFormat Static Methods -//---------------------------------------------------------------------------- - -std::map JSONFormat::initFormatInfos() { - std::map FormatInfos; - for (const auto &FormatInfoEntry : llvm::Registry::entries()) { - std::unique_ptr Info = FormatInfoEntry.instantiate(); - bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second; - if (!Inserted) { - llvm::report_fatal_error( - "FormatInfo is already registered for summary: " + - Info->ForSummary.str()); - } - } - return FormatInfos; -} - -//---------------------------------------------------------------------------- -// SummaryName -//---------------------------------------------------------------------------- - -namespace { - -SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) { - return SummaryName(SummaryNameStr.str()); -} - -llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); } - -} // namespace - -//---------------------------------------------------------------------------- -// EntityId -//---------------------------------------------------------------------------- - -EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const { - return makeEntityId(static_cast(EntityIdIndex)); -} - -uint64_t JSONFormat::entityIdToJSON(EntityId EI) const { - return static_cast(getIndex(EI)); -} - -//---------------------------------------------------------------------------- -// BuildNamespaceKind -//---------------------------------------------------------------------------- - -namespace { - -llvm::Expected -buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr) { - auto OptBuildNamespaceKind = - buildNamespaceKindFromString(BuildNamespaceKindStr); - if (!OptBuildNamespaceKind) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::InvalidBuildNamespaceKind, - BuildNamespaceKindStr) - .build(); - } - return *OptBuildNamespaceKind; -} - -// Provided for consistency with respect to rest of the codebase. -llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) { - return buildNamespaceKindToString(BNK); -} - -} // namespace - -//---------------------------------------------------------------------------- -// NestedBuildNamespace -//---------------------------------------------------------------------------- - -llvm::Expected -JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const { - auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString("kind"); - if (!OptBuildNamespaceKindStr) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "BuildNamespaceKind", "kind", "string") - .build(); - } - - auto ExpectedKind = buildNamespaceKindFromJSON(*OptBuildNamespaceKindStr); - if (!ExpectedKind) { - return ErrorBuilder::wrap(ExpectedKind.takeError()) - .context(ErrorMessages::ReadingFromField, "BuildNamespaceKind", "kind") - .build(); - } - - auto OptNameStr = BuildNamespaceObject.getString("name"); - if (!OptNameStr) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "BuildNamespaceName", "name", "string") - .build(); - } - - return {BuildNamespace(*ExpectedKind, *OptNameStr)}; -} - -Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const { - Object Result; - Result["kind"] = buildNamespaceKindToJSON(getKind(BN)); - Result["name"] = getName(BN); - return Result; -} - -//---------------------------------------------------------------------------- -// NestedBuildNamespace -//---------------------------------------------------------------------------- - -llvm::Expected JSONFormat::nestedBuildNamespaceFromJSON( - const Array &NestedBuildNamespaceArray) const { - std::vector Namespaces; - - size_t NamespaceCount = NestedBuildNamespaceArray.size(); - Namespaces.reserve(NamespaceCount); - - for (const auto &[Index, BuildNamespaceValue] : - llvm::enumerate(NestedBuildNamespaceArray)) { - - const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject(); - if (!BuildNamespaceObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtIndex, - "BuildNamespace", Index, "object") - .build(); - } - - auto ExpectedBuildNamespace = buildNamespaceFromJSON(*BuildNamespaceObject); - if (!ExpectedBuildNamespace) { - return ErrorBuilder::wrap(ExpectedBuildNamespace.takeError()) - .context(ErrorMessages::ReadingFromIndex, "BuildNamespace", Index) - .build(); - } - - Namespaces.push_back(std::move(*ExpectedBuildNamespace)); - } - - return NestedBuildNamespace(std::move(Namespaces)); -} - -Array JSONFormat::nestedBuildNamespaceToJSON( - const NestedBuildNamespace &NBN) const { - Array Result; - const auto &Namespaces = getNamespaces(NBN); - Result.reserve(Namespaces.size()); - - for (const auto &BN : Namespaces) { - Result.push_back(buildNamespaceToJSON(BN)); - } - - return Result; -} - -//---------------------------------------------------------------------------- -// EntityName -//---------------------------------------------------------------------------- - -llvm::Expected -JSONFormat::entityNameFromJSON(const Object &EntityNameObject) const { - const auto OptUSR = EntityNameObject.getString("usr"); - if (!OptUSR) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, "USR", - "usr", "string") - .build(); - } - - const auto OptSuffix = EntityNameObject.getString("suffix"); - if (!OptSuffix) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "Suffix", "suffix", "string") - .build(); - } - - const Array *OptNamespaceArray = EntityNameObject.getArray("namespace"); - if (!OptNamespaceArray) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "NestedBuildNamespace", "namespace", "array") - .build(); - } - - auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*OptNamespaceArray); - if (!ExpectedNamespace) { - return ErrorBuilder::wrap(ExpectedNamespace.takeError()) - .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace", - "namespace") - .build(); - } - - return EntityName{*OptUSR, *OptSuffix, std::move(*ExpectedNamespace)}; -} - -Object JSONFormat::entityNameToJSON(const EntityName &EN) const { - Object Result; - Result["usr"] = getUSR(EN); - Result["suffix"] = getSuffix(EN); - Result["namespace"] = nestedBuildNamespaceToJSON(getNamespace(EN)); - return Result; -} - -//---------------------------------------------------------------------------- -// EntityLinkageType -//---------------------------------------------------------------------------- - -namespace { - -llvm::Expected -entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr) { - auto OptEntityLinkageType = entityLinkageTypeFromString(EntityLinkageTypeStr); - if (!OptEntityLinkageType) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::InvalidEntityLinkageType, - EntityLinkageTypeStr) - .build(); - } - return *OptEntityLinkageType; -} - -// Provided for consistency with respect to rest of the codebase. -llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT) { - return entityLinkageTypeToString(LT); -} - -} // namespace - -//---------------------------------------------------------------------------- -// EntityLinkage -//---------------------------------------------------------------------------- - -llvm::Expected -JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const { - auto OptLinkageStr = EntityLinkageObject.getString("type"); - if (!OptLinkageStr) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityLinkageType", "type", "string") - .build(); - } - - auto ExpectedLinkageType = entityLinkageTypeFromJSON(*OptLinkageStr); - if (!ExpectedLinkageType) { - return ErrorBuilder::wrap(ExpectedLinkageType.takeError()) - .context(ErrorMessages::ReadingFromField, "EntityLinkageType", "type") - .build(); - } - - return EntityLinkage(*ExpectedLinkageType); -} - -Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const { - Object Result; - Result["type"] = entityLinkageTypeToJSON(getLinkage(EL)); - return Result; -} - -//---------------------------------------------------------------------------- -// EntityIdTableEntry -//---------------------------------------------------------------------------- - -llvm::Expected> -JSONFormat::entityIdTableEntryFromJSON( - const Object &EntityIdTableEntryObject) const { - - const Object *OptEntityNameObject = - EntityIdTableEntryObject.getObject("name"); - if (!OptEntityNameObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityName", "name", "object") - .build(); - } - - auto ExpectedEntityName = entityNameFromJSON(*OptEntityNameObject); - if (!ExpectedEntityName) { - return ErrorBuilder::wrap(ExpectedEntityName.takeError()) - .context(ErrorMessages::ReadingFromField, "EntityName", "name") - .build(); - } - - const Value *EntityIdIntValue = EntityIdTableEntryObject.get("id"); - if (!EntityIdIntValue) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "id", - "number (unsigned 64-bit integer)") - .build(); - } - - const std::optional OptEntityIdInt = - EntityIdIntValue->getAsUINT64(); - if (!OptEntityIdInt) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "id", - "number (unsigned 64-bit integer)") - .build(); - } - - EntityId EI = entityIdFromJSON(*OptEntityIdInt); - - return std::make_pair(std::move(*ExpectedEntityName), std::move(EI)); -} - -Object JSONFormat::entityIdTableEntryToJSON(const EntityName &EN, - EntityId EI) const { - Object Entry; - Entry["id"] = entityIdToJSON(EI); - Entry["name"] = entityNameToJSON(EN); - return Entry; -} - -//---------------------------------------------------------------------------- -// EntityIdTable -//---------------------------------------------------------------------------- - -llvm::Expected -JSONFormat::entityIdTableFromJSON(const Array &EntityIdTableArray) const { - EntityIdTable IdTable; - std::map &Entities = getEntities(IdTable); - - for (const auto &[Index, EntityIdTableEntryValue] : - llvm::enumerate(EntityIdTableArray)) { - - const Object *OptEntityIdTableEntryObject = - EntityIdTableEntryValue.getAsObject(); - if (!OptEntityIdTableEntryObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtIndex, - "EntityIdTable entry", Index, "object") - .build(); - } - - auto ExpectedEntityIdTableEntry = - entityIdTableEntryFromJSON(*OptEntityIdTableEntryObject); - if (!ExpectedEntityIdTableEntry) - return ErrorBuilder::wrap(ExpectedEntityIdTableEntry.takeError()) - .context(ErrorMessages::ReadingFromIndex, "EntityIdTable entry", - Index) - .build(); - - auto [EntityIt, EntityInserted] = - Entities.emplace(std::move(*ExpectedEntityIdTableEntry)); - if (!EntityInserted) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedInsertionOnDuplication, - "EntityIdTable entry", Index, - EntityIt->second) - .build(); - } - } - - return IdTable; -} - -Array JSONFormat::entityIdTableToJSON(const EntityIdTable &IdTable) const { - Array EntityIdTableArray; - const auto &Entities = getEntities(IdTable); - EntityIdTableArray.reserve(Entities.size()); - - for (const auto &[EntityName, EntityId] : Entities) { - EntityIdTableArray.push_back( - entityIdTableEntryToJSON(EntityName, EntityId)); - } - - return EntityIdTableArray; -} - -//---------------------------------------------------------------------------- -// LinkageTableEntry -//---------------------------------------------------------------------------- - -llvm::Expected> -JSONFormat::linkageTableEntryFromJSON( - const Object &LinkageTableEntryObject) const { - const Value *EntityIdIntValue = LinkageTableEntryObject.get("id"); - if (!EntityIdIntValue) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "id", - "number (unsigned 64-bit integer)") - .build(); - } - - const std::optional OptEntityIdInt = - EntityIdIntValue->getAsUINT64(); - if (!OptEntityIdInt) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "id", - "number (unsigned 64-bit integer)") - .build(); - } - - EntityId EI = entityIdFromJSON(*OptEntityIdInt); - - const Object *OptEntityLinkageObject = - LinkageTableEntryObject.getObject("linkage"); - if (!OptEntityLinkageObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityLinkage", "linkage", "object") - .build(); - } - - auto ExpectedEntityLinkage = entityLinkageFromJSON(*OptEntityLinkageObject); - if (!ExpectedEntityLinkage) { - return ErrorBuilder::wrap(ExpectedEntityLinkage.takeError()) - .context(ErrorMessages::ReadingFromField, "EntityLinkage", "linkage") - .build(); - } - - return std::make_pair(std::move(EI), std::move(*ExpectedEntityLinkage)); -} - -Object JSONFormat::linkageTableEntryToJSON(EntityId EI, - const EntityLinkage &EL) const { - Object Entry; - Entry["id"] = entityIdToJSON(EI); - Entry["linkage"] = entityLinkageToJSON(EL); - return Entry; -} - -//---------------------------------------------------------------------------- -// LinkageTable -//---------------------------------------------------------------------------- - -// ExpectedIds is the set of EntityIds from the IdTable that must appear in the -// linkage table—no more, no fewer. It is taken by value because it is consumed -// during parsing: each successfully matched id is erased from the set, and any -// ids remaining at the end are reported as missing. -llvm::Expected> -JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray, - std::set ExpectedIds) const { - std::map LinkageTable; - - for (const auto &[Index, LinkageTableEntryValue] : - llvm::enumerate(LinkageTableArray)) { - const Object *OptLinkageTableEntryObject = - LinkageTableEntryValue.getAsObject(); - if (!OptLinkageTableEntryObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtIndex, - "LinkageTable entry", Index, "object") - .build(); - } - - auto ExpectedLinkageTableEntry = - linkageTableEntryFromJSON(*OptLinkageTableEntryObject); - if (!ExpectedLinkageTableEntry) { - return ErrorBuilder::wrap(ExpectedLinkageTableEntry.takeError()) - .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index) - .build(); - } - - const EntityId EI = ExpectedLinkageTableEntry->first; - - auto [It, Inserted] = - LinkageTable.insert(std::move(*ExpectedLinkageTableEntry)); - if (!Inserted) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedInsertionOnDuplication, - "LinkageTable entry", Index, It->first) - .build(); - } - - if (ExpectedIds.erase(EI) == 0) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages::FailedToDeserializeLinkageTableExtraId, EI) - .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index) - .build(); - } - } - - if (!ExpectedIds.empty()) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages::FailedToDeserializeLinkageTableMissingId, - *ExpectedIds.begin()) - .build(); - } - - return LinkageTable; -} - -Array JSONFormat::linkageTableToJSON( - const std::map &LinkageTable) const { - Array Result; - Result.reserve(LinkageTable.size()); - - for (const auto &[EI, EL] : LinkageTable) { - Result.push_back(linkageTableEntryToJSON(EI, EL)); - } - - return Result; -} - -//---------------------------------------------------------------------------- -// EntitySummary -//---------------------------------------------------------------------------- - -llvm::Expected> -JSONFormat::entitySummaryFromJSON(const SummaryName &SN, - const Object &EntitySummaryObject, - EntityIdTable &IdTable) const { - auto InfoIt = FormatInfos.find(SN); - if (InfoIt == FormatInfos.end()) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages::FailedToDeserializeEntitySummaryNoFormatInfo, SN) - .build(); - } - - const auto &InfoEntry = InfoIt->second; - assert(InfoEntry.ForSummary == SN); - - EntityIdConverter Converter(*this); - return InfoEntry.Deserialize(EntitySummaryObject, IdTable, Converter); -} - -llvm::Expected -JSONFormat::entitySummaryToJSON(const SummaryName &SN, - const EntitySummary &ES) const { - auto InfoIt = FormatInfos.find(SN); - if (InfoIt == FormatInfos.end()) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages::FailedToSerializeEntitySummaryNoFormatInfo, SN) - .build(); - } - - const auto &InfoEntry = InfoIt->second; - assert(InfoEntry.ForSummary == SN); - - EntityIdConverter Converter(*this); - return InfoEntry.Serialize(ES, Converter); -} - -//---------------------------------------------------------------------------- -// EntityDataMapEntry -//---------------------------------------------------------------------------- - -llvm::Expected>> -JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject, - const SummaryName &SN, - EntityIdTable &IdTable) const { - - const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id"); - if (!EntityIdIntValue) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "entity_id", - "number (unsigned 64-bit integer)") - .build(); - } - - const std::optional OptEntityIdInt = - EntityIdIntValue->getAsUINT64(); - if (!OptEntityIdInt) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntityId", "entity_id", - "number (unsigned 64-bit integer)") - .build(); - } - - EntityId EI = entityIdFromJSON(*OptEntityIdInt); - - const Object *OptEntitySummaryObject = - EntityDataMapEntryObject.getObject("entity_summary"); - if (!OptEntitySummaryObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntitySummary", "entity_summary", "object") - .build(); - } - - auto ExpectedEntitySummary = - entitySummaryFromJSON(SN, *OptEntitySummaryObject, IdTable); - if (!ExpectedEntitySummary) { - return ErrorBuilder::wrap(ExpectedEntitySummary.takeError()) - .context(ErrorMessages::ReadingFromField, "EntitySummary", - "entity_summary") - .build(); - } - - if (*ExpectedEntitySummary == nullptr) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages::FailedToDeserializeEntitySummaryMissingData, SN) - .build(); - } - - auto ActualSN = (*ExpectedEntitySummary)->getSummaryName(); - if (SN != ActualSN) { - return ErrorBuilder::create( - std::errc::invalid_argument, - ErrorMessages:: - FailedToDeserializeEntitySummaryMismatchedSummaryName, - SN, ActualSN) - .build(); - } - - return std::make_pair(std::move(EI), std::move(*ExpectedEntitySummary)); -} - -llvm::Expected JSONFormat::entityDataMapEntryToJSON( - const EntityId EI, const std::unique_ptr &EntitySummary, - const SummaryName &SN) const { - Object Entry; - - Entry["entity_id"] = entityIdToJSON(EI); - - if (!EntitySummary) { - ErrorBuilder::fatal( - ErrorMessages::FailedToSerializeEntitySummaryMissingData, SN); - } - - const auto ActualSN = EntitySummary->getSummaryName(); - if (SN != ActualSN) { - ErrorBuilder::fatal( - ErrorMessages::FailedToSerializeEntitySummaryMismatchedSummaryName, SN, - ActualSN); - } - - auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, *EntitySummary); - if (!ExpectedEntitySummaryObject) { - return ErrorBuilder::wrap(ExpectedEntitySummaryObject.takeError()) - .context(ErrorMessages::WritingToField, "EntitySummary", - "entity_summary") - .build(); - } - - Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject); - - return Entry; -} - -//---------------------------------------------------------------------------- -// EntityDataMap -//---------------------------------------------------------------------------- - -llvm::Expected>> -JSONFormat::entityDataMapFromJSON(const SummaryName &SN, - const Array &EntityDataArray, - EntityIdTable &IdTable) const { - std::map> EntityDataMap; - - for (const auto &[Index, EntityDataMapEntryValue] : - llvm::enumerate(EntityDataArray)) { - - const Object *OptEntityDataMapEntryObject = - EntityDataMapEntryValue.getAsObject(); - if (!OptEntityDataMapEntryObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtIndex, - "EntitySummary entry", Index, "object") - .build(); - } - - auto ExpectedEntityDataMapEntry = - entityDataMapEntryFromJSON(*OptEntityDataMapEntryObject, SN, IdTable); - if (!ExpectedEntityDataMapEntry) { - return ErrorBuilder::wrap(ExpectedEntityDataMapEntry.takeError()) - .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry", - Index) - .build(); - } - - auto [DataIt, DataInserted] = - EntityDataMap.insert(std::move(*ExpectedEntityDataMapEntry)); - if (!DataInserted) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedInsertionOnDuplication, - "EntitySummary entry", Index, DataIt->first) - .build(); - } - } - - return std::move(EntityDataMap); -} - -llvm::Expected JSONFormat::entityDataMapToJSON( - const SummaryName &SN, - const std::map> &EntityDataMap) - const { - Array Result; - Result.reserve(EntityDataMap.size()); - - for (const auto &[Index, EntityDataMapEntry] : - llvm::enumerate(EntityDataMap)) { - const auto &[EntityId, EntitySummary] = EntityDataMapEntry; - - auto ExpectedEntityDataMapEntryObject = - entityDataMapEntryToJSON(EntityId, EntitySummary, SN); - - if (!ExpectedEntityDataMapEntryObject) { - return ErrorBuilder::wrap(ExpectedEntityDataMapEntryObject.takeError()) - .context(ErrorMessages::WritingToIndex, "EntitySummary entry", Index) - .build(); - } - - Result.push_back(std::move(*ExpectedEntityDataMapEntryObject)); - } - - return Result; -} - -//---------------------------------------------------------------------------- -// SummaryDataMapEntry -//---------------------------------------------------------------------------- - -llvm::Expected< - std::pair>>> -JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject, - EntityIdTable &IdTable) const { - - std::optional OptSummaryNameStr = - SummaryDataMapEntryObject.getString("summary_name"); - if (!OptSummaryNameStr) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "SummaryName", "summary_name", "string") - .build(); - } - - SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr); - - const Array *OptEntityDataArray = - SummaryDataMapEntryObject.getArray("summary_data"); - if (!OptEntityDataArray) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "EntitySummary entries", "summary_data", - "array") - .build(); - } - - auto ExpectedEntityDataMap = - entityDataMapFromJSON(SN, *OptEntityDataArray, IdTable); - if (!ExpectedEntityDataMap) - return ErrorBuilder::wrap(ExpectedEntityDataMap.takeError()) - .context(ErrorMessages::ReadingFromField, "EntitySummary entries", - "summary_data") - .build(); - - return std::make_pair(std::move(SN), std::move(*ExpectedEntityDataMap)); -} - -llvm::Expected JSONFormat::summaryDataMapEntryToJSON( - const SummaryName &SN, - const std::map> &SD) const { - Object Result; - - Result["summary_name"] = summaryNameToJSON(SN); - - auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, SD); - if (!ExpectedSummaryDataArray) { - return ErrorBuilder::wrap(ExpectedSummaryDataArray.takeError()) - .context(ErrorMessages::WritingToField, "EntitySummary entries", - "summary_data") - .build(); - } - - Result["summary_data"] = std::move(*ExpectedSummaryDataArray); - - return Result; -} - -//---------------------------------------------------------------------------- -// SummaryDataMap -//---------------------------------------------------------------------------- - -llvm::Expected< - std::map>>> -JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray, - EntityIdTable &IdTable) const { - std::map>> - SummaryDataMap; - - for (const auto &[Index, SummaryDataMapEntryValue] : - llvm::enumerate(SummaryDataArray)) { - - const Object *OptSummaryDataMapEntryObject = - SummaryDataMapEntryValue.getAsObject(); - if (!OptSummaryDataMapEntryObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtIndex, - "SummaryData entry", Index, "object") - .build(); - } - - auto ExpectedSummaryDataMapEntry = - summaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject, IdTable); - if (!ExpectedSummaryDataMapEntry) { - return ErrorBuilder::wrap(ExpectedSummaryDataMapEntry.takeError()) - .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index) - .build(); - } - - auto [SummaryIt, SummaryInserted] = - SummaryDataMap.emplace(std::move(*ExpectedSummaryDataMapEntry)); - if (!SummaryInserted) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedInsertionOnDuplication, - "SummaryData entry", Index, SummaryIt->first) - .build(); - } - } - - return std::move(SummaryDataMap); -} - -llvm::Expected JSONFormat::summaryDataMapToJSON( - const std::map>> - &SummaryDataMap) const { - Array Result; - Result.reserve(SummaryDataMap.size()); - - for (const auto &[Index, SummaryDataMapEntry] : - llvm::enumerate(SummaryDataMap)) { - const auto &[SummaryName, DataMap] = SummaryDataMapEntry; - - auto ExpectedSummaryDataMapObject = - summaryDataMapEntryToJSON(SummaryName, DataMap); - if (!ExpectedSummaryDataMapObject) { - return ErrorBuilder::wrap(ExpectedSummaryDataMapObject.takeError()) - .context(ErrorMessages::WritingToIndex, "SummaryData entry", Index) - .build(); - } - - Result.push_back(std::move(*ExpectedSummaryDataMapObject)); - } - - return std::move(Result); -} - -//---------------------------------------------------------------------------- -// TUSummary -//---------------------------------------------------------------------------- - -llvm::Expected JSONFormat::readTUSummary(llvm::StringRef Path) { - auto ExpectedJSON = readJSON(Path); - if (!ExpectedJSON) { - return ErrorBuilder::wrap(ExpectedJSON.takeError()) - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - Object *RootObjectPtr = ExpectedJSON->getAsObject(); - if (!RootObjectPtr) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObject, "TUSummary", - "object") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - const Object &RootObject = *RootObjectPtr; - - const Object *TUNamespaceObject = RootObject.getObject("tu_namespace"); - if (!TUNamespaceObject) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "BuildNamespace", "tu_namespace", "object") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject); - if (!ExpectedTUNamespace) { - return ErrorBuilder::wrap(ExpectedTUNamespace.takeError()) - .context(ErrorMessages::ReadingFromField, "BuildNamespace", - "tu_namespace") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - TUSummary Summary(std::move(*ExpectedTUNamespace)); - - { - const Array *IdTableArray = RootObject.getArray("id_table"); - if (!IdTableArray) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "IdTable", "id_table", "array") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - auto ExpectedIdTable = entityIdTableFromJSON(*IdTableArray); - if (!ExpectedIdTable) { - return ErrorBuilder::wrap(ExpectedIdTable.takeError()) - .context(ErrorMessages::ReadingFromField, "IdTable", "id_table") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - getIdTable(Summary) = std::move(*ExpectedIdTable); - } - - { - const Array *LinkageTableArray = RootObject.getArray("linkage_table"); - if (!LinkageTableArray) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "LinkageTable", "linkage_table", "array") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - auto ExpectedIdRange = - llvm::make_second_range(getEntities(getIdTable(Summary))); - std::set ExpectedIds(ExpectedIdRange.begin(), - ExpectedIdRange.end()); - - // Move ExpectedIds in since linkageTableFromJSON consumes it to verify - // that the linkage table contains exactly the ids present in the IdTable. - auto ExpectedLinkageTable = - linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds)); - if (!ExpectedLinkageTable) { - return ErrorBuilder::wrap(ExpectedLinkageTable.takeError()) - .context(ErrorMessages::ReadingFromField, "LinkageTable", - "linkage_table") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - getLinkageTable(Summary) = std::move(*ExpectedLinkageTable); - } - - { - const Array *SummaryDataArray = RootObject.getArray("data"); - if (!SummaryDataArray) { - return ErrorBuilder::create(std::errc::invalid_argument, - ErrorMessages::FailedToReadObjectAtField, - "SummaryData entries", "data", "array") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - auto ExpectedSummaryDataMap = - summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary)); - if (!ExpectedSummaryDataMap) { - return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError()) - .context(ErrorMessages::ReadingFromField, "SummaryData entries", - "data") - .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) - .build(); - } - - getData(Summary) = std::move(*ExpectedSummaryDataMap); - } - - return std::move(Summary); -} - -llvm::Error JSONFormat::writeTUSummary(const TUSummary &S, - llvm::StringRef Path) { - Object RootObject; - - RootObject["tu_namespace"] = buildNamespaceToJSON(getTUNamespace(S)); - - RootObject["id_table"] = entityIdTableToJSON(getIdTable(S)); - - RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S)); - - auto ExpectedDataObject = summaryDataMapToJSON(getData(S)); - if (!ExpectedDataObject) { - return ErrorBuilder::wrap(ExpectedDataObject.takeError()) - .context(ErrorMessages::WritingToFile, "TUSummary", Path) - .build(); - } - - RootObject["data"] = std::move(*ExpectedDataObject); - - if (auto Error = writeJSON(std::move(RootObject), Path)) { - return ErrorBuilder::wrap(std::move(Error)) - .context(ErrorMessages::WritingToFile, "TUSummary", Path) - .build(); - } - - return llvm::Error::success(); -} diff --git a/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.cpp new file mode 100644 index 0000000000000..3b9b49439dfa2 --- /dev/null +++ b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.cpp @@ -0,0 +1,596 @@ +//===- JSONFormatImpl.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "JSONFormatImpl.h" + +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" +#include "llvm/Support/Registry.h" + +LLVM_INSTANTIATE_REGISTRY(llvm::Registry) + +namespace clang::ssaf { + +//---------------------------------------------------------------------------- +// JSON Reader and Writer +//---------------------------------------------------------------------------- + +llvm::Expected readJSON(llvm::StringRef Path) { + if (!llvm::sys::fs::exists(Path)) { + return ErrorBuilder::create(std::errc::no_such_file_or_directory, + ErrorMessages::FailedToReadFile, Path, + ErrorMessages::FileNotFound) + .build(); + } + + if (llvm::sys::fs::is_directory(Path)) { + return ErrorBuilder::create(std::errc::is_a_directory, + ErrorMessages::FailedToReadFile, Path, + ErrorMessages::FileIsDirectory) + .build(); + } + + if (!Path.ends_with_insensitive(JSONFormatFileExtension)) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadFile, Path, + llvm::formatv(ErrorMessages::FileIsNotJSON, + JSONFormatFileExtension)) + .build(); + } + + auto BufferOrError = llvm::MemoryBuffer::getFile(Path); + if (!BufferOrError) { + const std::error_code EC = BufferOrError.getError(); + return ErrorBuilder::create(EC, ErrorMessages::FailedToReadFile, Path, + EC.message()) + .build(); + } + + return llvm::json::parse(BufferOrError.get()->getBuffer()); +} + +llvm::Error writeJSON(Value &&Value, llvm::StringRef Path) { + if (llvm::sys::fs::exists(Path)) { + return ErrorBuilder::create(std::errc::file_exists, + ErrorMessages::FailedToWriteFile, Path, + ErrorMessages::FileExists) + .build(); + } + + llvm::StringRef Dir = llvm::sys::path::parent_path(Path); + if (!Dir.empty() && !llvm::sys::fs::is_directory(Dir)) { + return ErrorBuilder::create(std::errc::no_such_file_or_directory, + ErrorMessages::FailedToWriteFile, Path, + ErrorMessages::ParentDirectoryNotFound) + .build(); + } + + if (!Path.ends_with_insensitive(JSONFormatFileExtension)) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToWriteFile, Path, + llvm::formatv(ErrorMessages::FileIsNotJSON, + JSONFormatFileExtension)) + .build(); + } + + std::error_code EC; + llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text); + + if (EC) { + return ErrorBuilder::create(EC, ErrorMessages::FailedToWriteFile, Path, + EC.message()) + .build(); + } + + OutStream << llvm::formatv("{0:2}\n", Value); + OutStream.flush(); + + // This path handles post-write stream errors (e.g. ENOSPC after buffered + // writes). It is difficult to exercise in unit tests so it is intentionally + // left without test coverage. + if (OutStream.has_error()) { + return ErrorBuilder::create(OutStream.error(), + ErrorMessages::FailedToWriteFile, Path, + OutStream.error().message()) + .build(); + } + + return llvm::Error::success(); +} + +//---------------------------------------------------------------------------- +// JSONFormat Static Methods +//---------------------------------------------------------------------------- + +std::map JSONFormat::initFormatInfos() { + std::map FormatInfos; + for (const auto &FormatInfoEntry : llvm::Registry::entries()) { + std::unique_ptr Info = FormatInfoEntry.instantiate(); + bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second; + if (!Inserted) { + llvm::report_fatal_error( + "FormatInfo is already registered for summary: " + + Info->ForSummary.str()); + } + } + return FormatInfos; +} + +//---------------------------------------------------------------------------- +// SummaryName +//---------------------------------------------------------------------------- + +SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) { + return SummaryName(SummaryNameStr.str()); +} + +llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); } + +//---------------------------------------------------------------------------- +// EntityId +//---------------------------------------------------------------------------- + +EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const { + return makeEntityId(static_cast(EntityIdIndex)); +} + +uint64_t JSONFormat::entityIdToJSON(EntityId EI) const { + return static_cast(getIndex(EI)); +} + +//---------------------------------------------------------------------------- +// BuildNamespaceKind +//---------------------------------------------------------------------------- + +llvm::Expected +buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr) { + auto OptBuildNamespaceKind = + buildNamespaceKindFromString(BuildNamespaceKindStr); + if (!OptBuildNamespaceKind) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::InvalidBuildNamespaceKind, + BuildNamespaceKindStr) + .build(); + } + return *OptBuildNamespaceKind; +} + +// Provided for consistency with respect to rest of the codebase. +llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) { + return buildNamespaceKindToString(BNK); +} + +//---------------------------------------------------------------------------- +// BuildNamespace +//---------------------------------------------------------------------------- + +llvm::Expected +JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const { + auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString("kind"); + if (!OptBuildNamespaceKindStr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "BuildNamespaceKind", "kind", "string") + .build(); + } + + auto ExpectedKind = buildNamespaceKindFromJSON(*OptBuildNamespaceKindStr); + if (!ExpectedKind) { + return ErrorBuilder::wrap(ExpectedKind.takeError()) + .context(ErrorMessages::ReadingFromField, "BuildNamespaceKind", "kind") + .build(); + } + + auto OptNameStr = BuildNamespaceObject.getString("name"); + if (!OptNameStr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "BuildNamespaceName", "name", "string") + .build(); + } + + return {BuildNamespace(*ExpectedKind, *OptNameStr)}; +} + +Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const { + Object Result; + Result["kind"] = buildNamespaceKindToJSON(getKind(BN)); + Result["name"] = getName(BN); + return Result; +} + +//---------------------------------------------------------------------------- +// NestedBuildNamespace +//---------------------------------------------------------------------------- + +llvm::Expected JSONFormat::nestedBuildNamespaceFromJSON( + const Array &NestedBuildNamespaceArray) const { + std::vector Namespaces; + + size_t NamespaceCount = NestedBuildNamespaceArray.size(); + Namespaces.reserve(NamespaceCount); + + for (const auto &[Index, BuildNamespaceValue] : + llvm::enumerate(NestedBuildNamespaceArray)) { + + const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject(); + if (!BuildNamespaceObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "BuildNamespace", Index, "object") + .build(); + } + + auto ExpectedBuildNamespace = buildNamespaceFromJSON(*BuildNamespaceObject); + if (!ExpectedBuildNamespace) { + return ErrorBuilder::wrap(ExpectedBuildNamespace.takeError()) + .context(ErrorMessages::ReadingFromIndex, "BuildNamespace", Index) + .build(); + } + + Namespaces.push_back(std::move(*ExpectedBuildNamespace)); + } + + return NestedBuildNamespace(std::move(Namespaces)); +} + +Array JSONFormat::nestedBuildNamespaceToJSON( + const NestedBuildNamespace &NBN) const { + Array Result; + const auto &Namespaces = getNamespaces(NBN); + Result.reserve(Namespaces.size()); + + for (const auto &BN : Namespaces) { + Result.push_back(buildNamespaceToJSON(BN)); + } + + return Result; +} + +//---------------------------------------------------------------------------- +// EntityName +//---------------------------------------------------------------------------- + +llvm::Expected +JSONFormat::entityNameFromJSON(const Object &EntityNameObject) const { + const auto OptUSR = EntityNameObject.getString("usr"); + if (!OptUSR) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, "USR", + "usr", "string") + .build(); + } + + const auto OptSuffix = EntityNameObject.getString("suffix"); + if (!OptSuffix) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "Suffix", "suffix", "string") + .build(); + } + + const Array *OptNamespaceArray = EntityNameObject.getArray("namespace"); + if (!OptNamespaceArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "NestedBuildNamespace", "namespace", "array") + .build(); + } + + auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*OptNamespaceArray); + if (!ExpectedNamespace) { + return ErrorBuilder::wrap(ExpectedNamespace.takeError()) + .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace", + "namespace") + .build(); + } + + return EntityName{*OptUSR, *OptSuffix, std::move(*ExpectedNamespace)}; +} + +Object JSONFormat::entityNameToJSON(const EntityName &EN) const { + Object Result; + Result["usr"] = getUSR(EN); + Result["suffix"] = getSuffix(EN); + Result["namespace"] = nestedBuildNamespaceToJSON(getNamespace(EN)); + return Result; +} + +//---------------------------------------------------------------------------- +// EntityLinkageType +//---------------------------------------------------------------------------- + +llvm::Expected +entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr) { + auto OptEntityLinkageType = entityLinkageTypeFromString(EntityLinkageTypeStr); + if (!OptEntityLinkageType) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::InvalidEntityLinkageType, + EntityLinkageTypeStr) + .build(); + } + return *OptEntityLinkageType; +} + +// Provided for consistency with respect to rest of the codebase. +llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT) { + return entityLinkageTypeToString(LT); +} + +//---------------------------------------------------------------------------- +// EntityLinkage +//---------------------------------------------------------------------------- + +llvm::Expected +JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const { + auto OptLinkageStr = EntityLinkageObject.getString("type"); + if (!OptLinkageStr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityLinkageType", "type", "string") + .build(); + } + + auto ExpectedLinkageType = entityLinkageTypeFromJSON(*OptLinkageStr); + if (!ExpectedLinkageType) { + return ErrorBuilder::wrap(ExpectedLinkageType.takeError()) + .context(ErrorMessages::ReadingFromField, "EntityLinkageType", "type") + .build(); + } + + return EntityLinkage(*ExpectedLinkageType); +} + +Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const { + Object Result; + Result["type"] = entityLinkageTypeToJSON(getLinkage(EL)); + return Result; +} + +//---------------------------------------------------------------------------- +// EntityIdTableEntry +//---------------------------------------------------------------------------- + +llvm::Expected> +JSONFormat::entityIdTableEntryFromJSON( + const Object &EntityIdTableEntryObject) const { + + const Object *OptEntityNameObject = + EntityIdTableEntryObject.getObject("name"); + if (!OptEntityNameObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityName", "name", "object") + .build(); + } + + auto ExpectedEntityName = entityNameFromJSON(*OptEntityNameObject); + if (!ExpectedEntityName) { + return ErrorBuilder::wrap(ExpectedEntityName.takeError()) + .context(ErrorMessages::ReadingFromField, "EntityName", "name") + .build(); + } + + const Value *EntityIdIntValue = EntityIdTableEntryObject.get("id"); + if (!EntityIdIntValue) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "id", + "number (unsigned 64-bit integer)") + .build(); + } + + const std::optional OptEntityIdInt = + EntityIdIntValue->getAsUINT64(); + if (!OptEntityIdInt) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "id", + "number (unsigned 64-bit integer)") + .build(); + } + + EntityId EI = entityIdFromJSON(*OptEntityIdInt); + + return std::make_pair(std::move(*ExpectedEntityName), std::move(EI)); +} + +Object JSONFormat::entityIdTableEntryToJSON(const EntityName &EN, + EntityId EI) const { + Object Entry; + Entry["id"] = entityIdToJSON(EI); + Entry["name"] = entityNameToJSON(EN); + return Entry; +} + +//---------------------------------------------------------------------------- +// EntityIdTable +//---------------------------------------------------------------------------- + +llvm::Expected +JSONFormat::entityIdTableFromJSON(const Array &EntityIdTableArray) const { + EntityIdTable IdTable; + std::map &Entities = getEntities(IdTable); + + for (const auto &[Index, EntityIdTableEntryValue] : + llvm::enumerate(EntityIdTableArray)) { + + const Object *OptEntityIdTableEntryObject = + EntityIdTableEntryValue.getAsObject(); + if (!OptEntityIdTableEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "EntityIdTable entry", Index, "object") + .build(); + } + + auto ExpectedEntityIdTableEntry = + entityIdTableEntryFromJSON(*OptEntityIdTableEntryObject); + if (!ExpectedEntityIdTableEntry) + return ErrorBuilder::wrap(ExpectedEntityIdTableEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "EntityIdTable entry", + Index) + .build(); + + auto [EntityIt, EntityInserted] = + Entities.emplace(std::move(*ExpectedEntityIdTableEntry)); + if (!EntityInserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "EntityIdTable entry", Index, + EntityIt->second) + .build(); + } + } + + return IdTable; +} + +Array JSONFormat::entityIdTableToJSON(const EntityIdTable &IdTable) const { + Array EntityIdTableArray; + const auto &Entities = getEntities(IdTable); + EntityIdTableArray.reserve(Entities.size()); + + for (const auto &[EntityName, EntityId] : Entities) { + EntityIdTableArray.push_back( + entityIdTableEntryToJSON(EntityName, EntityId)); + } + + return EntityIdTableArray; +} + +//---------------------------------------------------------------------------- +// LinkageTableEntry +//---------------------------------------------------------------------------- + +llvm::Expected> +JSONFormat::linkageTableEntryFromJSON( + const Object &LinkageTableEntryObject) const { + const Value *EntityIdIntValue = LinkageTableEntryObject.get("id"); + if (!EntityIdIntValue) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "id", + "number (unsigned 64-bit integer)") + .build(); + } + + const std::optional OptEntityIdInt = + EntityIdIntValue->getAsUINT64(); + if (!OptEntityIdInt) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "id", + "number (unsigned 64-bit integer)") + .build(); + } + + EntityId EI = entityIdFromJSON(*OptEntityIdInt); + + const Object *OptEntityLinkageObject = + LinkageTableEntryObject.getObject("linkage"); + if (!OptEntityLinkageObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityLinkage", "linkage", "object") + .build(); + } + + auto ExpectedEntityLinkage = entityLinkageFromJSON(*OptEntityLinkageObject); + if (!ExpectedEntityLinkage) { + return ErrorBuilder::wrap(ExpectedEntityLinkage.takeError()) + .context(ErrorMessages::ReadingFromField, "EntityLinkage", "linkage") + .build(); + } + + return std::make_pair(std::move(EI), std::move(*ExpectedEntityLinkage)); +} + +Object JSONFormat::linkageTableEntryToJSON(EntityId EI, + const EntityLinkage &EL) const { + Object Entry; + Entry["id"] = entityIdToJSON(EI); + Entry["linkage"] = entityLinkageToJSON(EL); + return Entry; +} + +//---------------------------------------------------------------------------- +// LinkageTable +//---------------------------------------------------------------------------- + +// ExpectedIds is the set of EntityIds from the IdTable that must appear in the +// linkage table—no more, no fewer. It is taken by value because it is consumed +// during parsing: each successfully matched id is erased from the set, and any +// ids remaining at the end are reported as missing. +llvm::Expected> +JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray, + std::set ExpectedIds) const { + std::map LinkageTable; + + for (const auto &[Index, LinkageTableEntryValue] : + llvm::enumerate(LinkageTableArray)) { + const Object *OptLinkageTableEntryObject = + LinkageTableEntryValue.getAsObject(); + if (!OptLinkageTableEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "LinkageTable entry", Index, "object") + .build(); + } + + auto ExpectedLinkageTableEntry = + linkageTableEntryFromJSON(*OptLinkageTableEntryObject); + if (!ExpectedLinkageTableEntry) { + return ErrorBuilder::wrap(ExpectedLinkageTableEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index) + .build(); + } + + const EntityId EI = ExpectedLinkageTableEntry->first; + + auto [It, Inserted] = + LinkageTable.insert(std::move(*ExpectedLinkageTableEntry)); + if (!Inserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "LinkageTable entry", Index, It->first) + .build(); + } + + if (ExpectedIds.erase(EI) == 0) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages::FailedToDeserializeLinkageTableExtraId, EI) + .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index) + .build(); + } + } + + if (!ExpectedIds.empty()) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages::FailedToDeserializeLinkageTableMissingId, + *ExpectedIds.begin()) + .build(); + } + + return LinkageTable; +} + +Array JSONFormat::linkageTableToJSON( + const std::map &LinkageTable) const { + Array Result; + Result.reserve(LinkageTable.size()); + + for (const auto &[EI, EL] : LinkageTable) { + Result.push_back(linkageTableEntryToJSON(EI, EL)); + } + + return Result; +} + +} // namespace clang::ssaf diff --git a/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.h new file mode 100644 index 0000000000000..3ba651bbc507f --- /dev/null +++ b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/JSONFormatImpl.h @@ -0,0 +1,148 @@ +//===- JSONFormatImpl.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Internal implementation header shared by all translation units in the +// JSONFormat subdirectory. Not part of the public API. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_LIB_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H +#define CLANG_LIB_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H + +#include "../../ModelStringConversions.h" +#include "clang/Analysis/Scalable/Model/EntityLinkage.h" +#include "clang/Analysis/Scalable/Serialization/JSONFormat.h" +#include "clang/Analysis/Scalable/Support/ErrorBuilder.h" +#include "clang/Analysis/Scalable/Support/FormatProviders.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Registry.h" + +namespace clang::ssaf { + +using Array = llvm::json::Array; +using Object = llvm::json::Object; +using Value = llvm::json::Value; + +//---------------------------------------------------------------------------- +// File Format Constant +//---------------------------------------------------------------------------- + +inline constexpr const char *JSONFormatFileExtension = ".json"; + +//---------------------------------------------------------------------------- +// Error Message Constants +//---------------------------------------------------------------------------- + +namespace ErrorMessages { + +inline constexpr const char *FailedToReadFile = + "failed to read file '{0}': {1}"; +inline constexpr const char *FailedToWriteFile = + "failed to write file '{0}': {1}"; +inline constexpr const char *FileNotFound = "file does not exist"; +inline constexpr const char *FileIsDirectory = + "path is a directory, not a file"; +inline constexpr const char *FileIsNotJSON = + "file does not end with '{0}' extension"; +inline constexpr const char *FileExists = "file already exists"; +inline constexpr const char *ParentDirectoryNotFound = + "parent directory does not exist"; + +inline constexpr const char *ReadingFromField = "reading {0} from field '{1}'"; +inline constexpr const char *WritingToField = "writing {0} to field '{1}'"; +inline constexpr const char *ReadingFromIndex = "reading {0} from index '{1}'"; +inline constexpr const char *WritingToIndex = "writing {0} to index '{1}'"; +inline constexpr const char *ReadingFromFile = "reading {0} from file '{1}'"; +inline constexpr const char *WritingToFile = "writing {0} to file '{1}'"; + +inline constexpr const char *FailedInsertionOnDuplication = + "failed to insert {0} at index '{1}': encountered duplicate '{2}'"; + +inline constexpr const char *FailedToReadObject = + "failed to read {0}: expected JSON {1}"; +inline constexpr const char *FailedToReadObjectAtField = + "failed to read {0} from field '{1}': expected JSON {2}"; +inline constexpr const char *FailedToReadObjectAtIndex = + "failed to read {0} from index '{1}': expected JSON {2}"; + +inline constexpr const char *FailedToDeserializeEntitySummaryNoFormatInfo = + "failed to deserialize EntitySummary: no FormatInfo registered for '{0}'"; +inline constexpr const char *FailedToSerializeEntitySummaryNoFormatInfo = + "failed to serialize EntitySummary: no FormatInfo registered for '{0}'"; + +inline constexpr const char *FailedToDeserializeEntitySummaryMissingData = + "failed to deserialize EntitySummary: null EntitySummary data for '{0}'"; +inline constexpr const char *FailedToSerializeEntitySummaryMissingData = + "JSONFormat - null EntitySummary data for '{0}'"; + +inline constexpr const char + *FailedToDeserializeEntitySummaryMismatchedSummaryName = + "failed to deserialize EntitySummary: EntitySummary data for '{0}' " + "reports mismatched '{1}'"; +inline constexpr const char + *FailedToSerializeEntitySummaryMismatchedSummaryName = + "JSONFormat - EntitySummary data for '{0}' reports mismatched '{1}'"; + +inline constexpr const char *InvalidBuildNamespaceKind = + "invalid BuildNamespaceKind value '{0}' for field 'kind'"; + +inline constexpr const char *InvalidEntityLinkageType = + "invalid EntityLinkageType value '{0}' for field 'type'"; + +inline constexpr const char *FailedToDeserializeLinkageTableExtraId = + "failed to deserialize LinkageTable: extra '{0}' not present in IdTable"; + +inline constexpr const char *FailedToDeserializeLinkageTableMissingId = + "failed to deserialize LinkageTable: missing '{0}' present in IdTable"; + +} // namespace ErrorMessages + +//---------------------------------------------------------------------------- +// JSON Reader and Writer +//---------------------------------------------------------------------------- + +llvm::Expected readJSON(llvm::StringRef Path); +llvm::Error writeJSON(Value &&V, llvm::StringRef Path); + +//---------------------------------------------------------------------------- +// SummaryName helpers (free functions, anonymous-namespace in .cpp) +//---------------------------------------------------------------------------- + +SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr); +llvm::StringRef summaryNameToJSON(const SummaryName &SN); + +//---------------------------------------------------------------------------- +// BuildNamespaceKind helpers +//---------------------------------------------------------------------------- + +llvm::Expected +buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr); + +// Provided for consistency with respect to rest of the codebase. +llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK); + +//---------------------------------------------------------------------------- +// EntityLinkageType helpers +//---------------------------------------------------------------------------- + +llvm::Expected +entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr); + +// Provided for consistency with respect to rest of the codebase. +llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT); + +} // namespace clang::ssaf + +#endif // CLANG_LIB_ANALYSIS_SCALABLE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H diff --git a/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummary.cpp b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummary.cpp new file mode 100644 index 0000000000000..19612bb380aef --- /dev/null +++ b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummary.cpp @@ -0,0 +1,504 @@ +//===- TUSummary.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "JSONFormatImpl.h" + +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" + +namespace clang::ssaf { + +//---------------------------------------------------------------------------- +// EntitySummary +//---------------------------------------------------------------------------- + +llvm::Expected> +JSONFormat::entitySummaryFromJSON(const SummaryName &SN, + const Object &EntitySummaryObject, + EntityIdTable &IdTable) const { + auto InfoIt = FormatInfos.find(SN); + if (InfoIt == FormatInfos.end()) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages::FailedToDeserializeEntitySummaryNoFormatInfo, SN) + .build(); + } + + const auto &InfoEntry = InfoIt->second; + assert(InfoEntry.ForSummary == SN); + + EntityIdConverter Converter(*this); + return InfoEntry.Deserialize(EntitySummaryObject, IdTable, Converter); +} + +llvm::Expected +JSONFormat::entitySummaryToJSON(const SummaryName &SN, + const EntitySummary &ES) const { + auto InfoIt = FormatInfos.find(SN); + if (InfoIt == FormatInfos.end()) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages::FailedToSerializeEntitySummaryNoFormatInfo, SN) + .build(); + } + + const auto &InfoEntry = InfoIt->second; + assert(InfoEntry.ForSummary == SN); + + EntityIdConverter Converter(*this); + return InfoEntry.Serialize(ES, Converter); +} + +//---------------------------------------------------------------------------- +// EntityDataMapEntry +//---------------------------------------------------------------------------- + +llvm::Expected>> +JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject, + const SummaryName &SN, + EntityIdTable &IdTable) const { + + const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id"); + if (!EntityIdIntValue) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "entity_id", + "number (unsigned 64-bit integer)") + .build(); + } + + const std::optional OptEntityIdInt = + EntityIdIntValue->getAsUINT64(); + if (!OptEntityIdInt) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "entity_id", + "number (unsigned 64-bit integer)") + .build(); + } + + EntityId EI = entityIdFromJSON(*OptEntityIdInt); + + const Object *OptEntitySummaryObject = + EntityDataMapEntryObject.getObject("entity_summary"); + if (!OptEntitySummaryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntitySummary", "entity_summary", "object") + .build(); + } + + auto ExpectedEntitySummary = + entitySummaryFromJSON(SN, *OptEntitySummaryObject, IdTable); + if (!ExpectedEntitySummary) { + return ErrorBuilder::wrap(ExpectedEntitySummary.takeError()) + .context(ErrorMessages::ReadingFromField, "EntitySummary", + "entity_summary") + .build(); + } + + if (*ExpectedEntitySummary == nullptr) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages::FailedToDeserializeEntitySummaryMissingData, SN) + .build(); + } + + auto ActualSN = (*ExpectedEntitySummary)->getSummaryName(); + if (SN != ActualSN) { + return ErrorBuilder::create( + std::errc::invalid_argument, + ErrorMessages:: + FailedToDeserializeEntitySummaryMismatchedSummaryName, + SN, ActualSN) + .build(); + } + + return std::make_pair(std::move(EI), std::move(*ExpectedEntitySummary)); +} + +llvm::Expected JSONFormat::entityDataMapEntryToJSON( + const EntityId EI, const std::unique_ptr &EntitySummary, + const SummaryName &SN) const { + Object Entry; + + Entry["entity_id"] = entityIdToJSON(EI); + + if (!EntitySummary) { + ErrorBuilder::fatal( + ErrorMessages::FailedToSerializeEntitySummaryMissingData, SN); + } + + const auto ActualSN = EntitySummary->getSummaryName(); + if (SN != ActualSN) { + ErrorBuilder::fatal( + ErrorMessages::FailedToSerializeEntitySummaryMismatchedSummaryName, SN, + ActualSN); + } + + auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, *EntitySummary); + if (!ExpectedEntitySummaryObject) { + return ErrorBuilder::wrap(ExpectedEntitySummaryObject.takeError()) + .context(ErrorMessages::WritingToField, "EntitySummary", + "entity_summary") + .build(); + } + + Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject); + + return Entry; +} + +//---------------------------------------------------------------------------- +// EntityDataMap +//---------------------------------------------------------------------------- + +llvm::Expected>> +JSONFormat::entityDataMapFromJSON(const SummaryName &SN, + const Array &EntityDataArray, + EntityIdTable &IdTable) const { + std::map> EntityDataMap; + + for (const auto &[Index, EntityDataMapEntryValue] : + llvm::enumerate(EntityDataArray)) { + + const Object *OptEntityDataMapEntryObject = + EntityDataMapEntryValue.getAsObject(); + if (!OptEntityDataMapEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "EntitySummary entry", Index, "object") + .build(); + } + + auto ExpectedEntityDataMapEntry = + entityDataMapEntryFromJSON(*OptEntityDataMapEntryObject, SN, IdTable); + if (!ExpectedEntityDataMapEntry) { + return ErrorBuilder::wrap(ExpectedEntityDataMapEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry", + Index) + .build(); + } + + auto [DataIt, DataInserted] = + EntityDataMap.insert(std::move(*ExpectedEntityDataMapEntry)); + if (!DataInserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "EntitySummary entry", Index, DataIt->first) + .build(); + } + } + + return std::move(EntityDataMap); +} + +llvm::Expected JSONFormat::entityDataMapToJSON( + const SummaryName &SN, + const std::map> &EntityDataMap) + const { + Array Result; + Result.reserve(EntityDataMap.size()); + + for (const auto &[Index, EntityDataMapEntry] : + llvm::enumerate(EntityDataMap)) { + const auto &[EntityId, EntitySummary] = EntityDataMapEntry; + + auto ExpectedEntityDataMapEntryObject = + entityDataMapEntryToJSON(EntityId, EntitySummary, SN); + + if (!ExpectedEntityDataMapEntryObject) { + return ErrorBuilder::wrap(ExpectedEntityDataMapEntryObject.takeError()) + .context(ErrorMessages::WritingToIndex, "EntitySummary entry", Index) + .build(); + } + + Result.push_back(std::move(*ExpectedEntityDataMapEntryObject)); + } + + return Result; +} + +//---------------------------------------------------------------------------- +// SummaryDataMapEntry +//---------------------------------------------------------------------------- + +llvm::Expected< + std::pair>>> +JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject, + EntityIdTable &IdTable) const { + + std::optional OptSummaryNameStr = + SummaryDataMapEntryObject.getString("summary_name"); + if (!OptSummaryNameStr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "SummaryName", "summary_name", "string") + .build(); + } + + SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr); + + const Array *OptEntityDataArray = + SummaryDataMapEntryObject.getArray("summary_data"); + if (!OptEntityDataArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntitySummary entries", "summary_data", + "array") + .build(); + } + + auto ExpectedEntityDataMap = + entityDataMapFromJSON(SN, *OptEntityDataArray, IdTable); + if (!ExpectedEntityDataMap) + return ErrorBuilder::wrap(ExpectedEntityDataMap.takeError()) + .context(ErrorMessages::ReadingFromField, "EntitySummary entries", + "summary_data") + .build(); + + return std::make_pair(std::move(SN), std::move(*ExpectedEntityDataMap)); +} + +llvm::Expected JSONFormat::summaryDataMapEntryToJSON( + const SummaryName &SN, + const std::map> &SD) const { + Object Result; + + Result["summary_name"] = summaryNameToJSON(SN); + + auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, SD); + if (!ExpectedSummaryDataArray) { + return ErrorBuilder::wrap(ExpectedSummaryDataArray.takeError()) + .context(ErrorMessages::WritingToField, "EntitySummary entries", + "summary_data") + .build(); + } + + Result["summary_data"] = std::move(*ExpectedSummaryDataArray); + + return Result; +} + +//---------------------------------------------------------------------------- +// SummaryDataMap +//---------------------------------------------------------------------------- + +llvm::Expected< + std::map>>> +JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray, + EntityIdTable &IdTable) const { + std::map>> + SummaryDataMap; + + for (const auto &[Index, SummaryDataMapEntryValue] : + llvm::enumerate(SummaryDataArray)) { + + const Object *OptSummaryDataMapEntryObject = + SummaryDataMapEntryValue.getAsObject(); + if (!OptSummaryDataMapEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "SummaryData entry", Index, "object") + .build(); + } + + auto ExpectedSummaryDataMapEntry = + summaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject, IdTable); + if (!ExpectedSummaryDataMapEntry) { + return ErrorBuilder::wrap(ExpectedSummaryDataMapEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index) + .build(); + } + + auto [SummaryIt, SummaryInserted] = + SummaryDataMap.emplace(std::move(*ExpectedSummaryDataMapEntry)); + if (!SummaryInserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "SummaryData entry", Index, SummaryIt->first) + .build(); + } + } + + return std::move(SummaryDataMap); +} + +llvm::Expected JSONFormat::summaryDataMapToJSON( + const std::map>> + &SummaryDataMap) const { + Array Result; + Result.reserve(SummaryDataMap.size()); + + for (const auto &[Index, SummaryDataMapEntry] : + llvm::enumerate(SummaryDataMap)) { + const auto &[SummaryName, DataMap] = SummaryDataMapEntry; + + auto ExpectedSummaryDataMapObject = + summaryDataMapEntryToJSON(SummaryName, DataMap); + if (!ExpectedSummaryDataMapObject) { + return ErrorBuilder::wrap(ExpectedSummaryDataMapObject.takeError()) + .context(ErrorMessages::WritingToIndex, "SummaryData entry", Index) + .build(); + } + + Result.push_back(std::move(*ExpectedSummaryDataMapObject)); + } + + return std::move(Result); +} + +//---------------------------------------------------------------------------- +// TUSummary +//---------------------------------------------------------------------------- + +llvm::Expected JSONFormat::readTUSummary(llvm::StringRef Path) { + auto ExpectedJSON = readJSON(Path); + if (!ExpectedJSON) { + return ErrorBuilder::wrap(ExpectedJSON.takeError()) + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + Object *RootObjectPtr = ExpectedJSON->getAsObject(); + if (!RootObjectPtr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObject, "TUSummary", + "object") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + const Object &RootObject = *RootObjectPtr; + + const Object *TUNamespaceObject = RootObject.getObject("tu_namespace"); + if (!TUNamespaceObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "BuildNamespace", "tu_namespace", "object") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject); + if (!ExpectedTUNamespace) { + return ErrorBuilder::wrap(ExpectedTUNamespace.takeError()) + .context(ErrorMessages::ReadingFromField, "BuildNamespace", + "tu_namespace") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + TUSummary Summary(std::move(*ExpectedTUNamespace)); + + { + const Array *IdTableArray = RootObject.getArray("id_table"); + if (!IdTableArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "IdTable", "id_table", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedIdTable = entityIdTableFromJSON(*IdTableArray); + if (!ExpectedIdTable) { + return ErrorBuilder::wrap(ExpectedIdTable.takeError()) + .context(ErrorMessages::ReadingFromField, "IdTable", "id_table") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getIdTable(Summary) = std::move(*ExpectedIdTable); + } + + { + const Array *LinkageTableArray = RootObject.getArray("linkage_table"); + if (!LinkageTableArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "LinkageTable", "linkage_table", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedIdRange = + llvm::make_second_range(getEntities(getIdTable(Summary))); + std::set ExpectedIds(ExpectedIdRange.begin(), + ExpectedIdRange.end()); + + // Move ExpectedIds in since linkageTableFromJSON consumes it to verify + // that the linkage table contains exactly the ids present in the IdTable. + auto ExpectedLinkageTable = + linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds)); + if (!ExpectedLinkageTable) { + return ErrorBuilder::wrap(ExpectedLinkageTable.takeError()) + .context(ErrorMessages::ReadingFromField, "LinkageTable", + "linkage_table") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getLinkageTable(Summary) = std::move(*ExpectedLinkageTable); + } + + { + const Array *SummaryDataArray = RootObject.getArray("data"); + if (!SummaryDataArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "SummaryData entries", "data", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedSummaryDataMap = + summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary)); + if (!ExpectedSummaryDataMap) { + return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError()) + .context(ErrorMessages::ReadingFromField, "SummaryData entries", + "data") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getData(Summary) = std::move(*ExpectedSummaryDataMap); + } + + return std::move(Summary); +} + +llvm::Error JSONFormat::writeTUSummary(const TUSummary &S, + llvm::StringRef Path) { + Object RootObject; + + RootObject["tu_namespace"] = buildNamespaceToJSON(getTUNamespace(S)); + + RootObject["id_table"] = entityIdTableToJSON(getIdTable(S)); + + RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S)); + + auto ExpectedDataObject = summaryDataMapToJSON(getData(S)); + if (!ExpectedDataObject) { + return ErrorBuilder::wrap(ExpectedDataObject.takeError()) + .context(ErrorMessages::WritingToFile, "TUSummary", Path) + .build(); + } + + RootObject["data"] = std::move(*ExpectedDataObject); + + if (auto Error = writeJSON(std::move(RootObject), Path)) { + return ErrorBuilder::wrap(std::move(Error)) + .context(ErrorMessages::WritingToFile, "TUSummary", Path) + .build(); + } + + return llvm::Error::success(); +} + +} // namespace clang::ssaf diff --git a/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummaryEncoding.cpp b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummaryEncoding.cpp new file mode 100644 index 0000000000000..bcf534e6e7e7e --- /dev/null +++ b/clang/lib/Analysis/Scalable/Serialization/JSONFormat/TUSummaryEncoding.cpp @@ -0,0 +1,407 @@ +//===- TUSummaryEncoding.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "JSONFormatImpl.h" + +#include "clang/Analysis/Scalable/EntityLinker/EntitySummaryEncoding.h" +#include "clang/Analysis/Scalable/EntityLinker/TUSummaryEncoding.h" + +namespace clang::ssaf { + +//---------------------------------------------------------------------------- +// JSONEntitySummaryEncoding +//---------------------------------------------------------------------------- + +namespace { + +class JSONEntitySummaryEncoding final : public EntitySummaryEncoding { + friend JSONFormat; + +public: + void + patch(const std::map &EntityResolutionTable) override { + ErrorBuilder::fatal("will be implemented in the future"); + } + +private: + explicit JSONEntitySummaryEncoding(llvm::json::Value Data) + : Data(std::move(Data)) {} + + llvm::json::Value Data; +}; + +} // namespace + +//---------------------------------------------------------------------------- +// EncodingDataMapEntry +//---------------------------------------------------------------------------- + +llvm::Expected>> +JSONFormat::encodingDataMapEntryFromJSON( + const Object &EntityDataMapEntryObject) const { + const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id"); + if (!EntityIdIntValue) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "entity_id", + "number (unsigned 64-bit integer)") + .build(); + } + + const std::optional OptEntityIdInt = + EntityIdIntValue->getAsUINT64(); + if (!OptEntityIdInt) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntityId", "entity_id", + "number (unsigned 64-bit integer)") + .build(); + } + + EntityId EI = entityIdFromJSON(*OptEntityIdInt); + + const Object *OptEntitySummaryObject = + EntityDataMapEntryObject.getObject("entity_summary"); + if (!OptEntitySummaryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntitySummary", "entity_summary", "object") + .build(); + } + + std::unique_ptr Encoding( + new JSONEntitySummaryEncoding(Value(Object(*OptEntitySummaryObject)))); + + return std::make_pair(std::move(EI), std::move(Encoding)); +} + +Object JSONFormat::encodingDataMapEntryToJSON( + EntityId EI, const std::unique_ptr &Encoding) const { + Object Entry; + Entry["entity_id"] = entityIdToJSON(EI); + + // All EntitySummaryEncoding objects stored in a TUSummaryEncoding read by + // JSONFormat are JSONEntitySummaryEncoding instances, since + // encodingDataMapEntryFromJSON is the only place that creates them. + auto *JSONEncoding = static_cast(Encoding.get()); + Entry["entity_summary"] = JSONEncoding->Data; + + return Entry; +} + +//---------------------------------------------------------------------------- +// EncodingDataMap +//---------------------------------------------------------------------------- + +llvm::Expected>> +JSONFormat::encodingDataMapFromJSON(const Array &EntityDataArray) const { + std::map> EncodingDataMap; + + for (const auto &[Index, EntityDataMapEntryValue] : + llvm::enumerate(EntityDataArray)) { + + const Object *OptEntityDataMapEntryObject = + EntityDataMapEntryValue.getAsObject(); + if (!OptEntityDataMapEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "EntitySummary entry", Index, "object") + .build(); + } + + auto ExpectedEntry = + encodingDataMapEntryFromJSON(*OptEntityDataMapEntryObject); + if (!ExpectedEntry) { + return ErrorBuilder::wrap(ExpectedEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry", + Index) + .build(); + } + + auto [DataIt, DataInserted] = + EncodingDataMap.insert(std::move(*ExpectedEntry)); + if (!DataInserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "EntitySummary entry", Index, DataIt->first) + .build(); + } + } + + return std::move(EncodingDataMap); +} + +Array JSONFormat::encodingDataMapToJSON( + const std::map> + &EncodingDataMap) const { + Array Result; + Result.reserve(EncodingDataMap.size()); + + for (const auto &[EI, Encoding] : EncodingDataMap) { + Result.push_back(encodingDataMapEntryToJSON(EI, Encoding)); + } + + return Result; +} + +//---------------------------------------------------------------------------- +// EncodingSummaryDataMapEntry +//---------------------------------------------------------------------------- + +llvm::Expected>>> +JSONFormat::encodingSummaryDataMapEntryFromJSON( + const Object &SummaryDataMapEntryObject) const { + std::optional OptSummaryNameStr = + SummaryDataMapEntryObject.getString("summary_name"); + if (!OptSummaryNameStr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "SummaryName", "summary_name", "string") + .build(); + } + + SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr); + + const Array *OptEntityDataArray = + SummaryDataMapEntryObject.getArray("summary_data"); + if (!OptEntityDataArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "EntitySummary entries", "summary_data", + "array") + .build(); + } + + auto ExpectedEncodingDataMap = encodingDataMapFromJSON(*OptEntityDataArray); + if (!ExpectedEncodingDataMap) + return ErrorBuilder::wrap(ExpectedEncodingDataMap.takeError()) + .context(ErrorMessages::ReadingFromField, "EntitySummary entries", + "summary_data") + .build(); + + return std::make_pair(std::move(SN), std::move(*ExpectedEncodingDataMap)); +} + +Object JSONFormat::encodingSummaryDataMapEntryToJSON( + const SummaryName &SN, + const std::map> + &EncodingMap) const { + Object Result; + + Result["summary_name"] = summaryNameToJSON(SN); + Result["summary_data"] = encodingDataMapToJSON(EncodingMap); + + return Result; +} + +//---------------------------------------------------------------------------- +// EncodingSummaryDataMap +//---------------------------------------------------------------------------- + +llvm::Expected>>> +JSONFormat::encodingSummaryDataMapFromJSON( + const Array &SummaryDataArray) const { + std::map>> + EncodingSummaryDataMap; + + for (const auto &[Index, SummaryDataMapEntryValue] : + llvm::enumerate(SummaryDataArray)) { + + const Object *OptSummaryDataMapEntryObject = + SummaryDataMapEntryValue.getAsObject(); + if (!OptSummaryDataMapEntryObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtIndex, + "SummaryData entry", Index, "object") + .build(); + } + + auto ExpectedEntry = + encodingSummaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject); + if (!ExpectedEntry) { + return ErrorBuilder::wrap(ExpectedEntry.takeError()) + .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index) + .build(); + } + + auto [SummaryIt, SummaryInserted] = + EncodingSummaryDataMap.emplace(std::move(*ExpectedEntry)); + if (!SummaryInserted) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedInsertionOnDuplication, + "SummaryData entry", Index, SummaryIt->first) + .build(); + } + } + + return std::move(EncodingSummaryDataMap); +} + +Array JSONFormat::encodingSummaryDataMapToJSON( + const std::map>> + &EncodingSummaryDataMap) const { + Array Result; + Result.reserve(EncodingSummaryDataMap.size()); + + for (const auto &[SN, EncodingMap] : EncodingSummaryDataMap) { + Result.push_back(encodingSummaryDataMapEntryToJSON(SN, EncodingMap)); + } + + return Result; +} + +//---------------------------------------------------------------------------- +// TUSummaryEncoding +//---------------------------------------------------------------------------- + +llvm::Expected +JSONFormat::readTUSummaryEncoding(llvm::StringRef Path) { + auto ExpectedJSON = readJSON(Path); + if (!ExpectedJSON) { + return ErrorBuilder::wrap(ExpectedJSON.takeError()) + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + Object *RootObjectPtr = ExpectedJSON->getAsObject(); + if (!RootObjectPtr) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObject, "TUSummary", + "object") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + const Object &RootObject = *RootObjectPtr; + + const Object *TUNamespaceObject = RootObject.getObject("tu_namespace"); + if (!TUNamespaceObject) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "BuildNamespace", "tu_namespace", "object") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject); + if (!ExpectedTUNamespace) { + return ErrorBuilder::wrap(ExpectedTUNamespace.takeError()) + .context(ErrorMessages::ReadingFromField, "BuildNamespace", + "tu_namespace") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + TUSummaryEncoding Encoding(std::move(*ExpectedTUNamespace)); + + { + const Array *IdTableArray = RootObject.getArray("id_table"); + if (!IdTableArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "IdTable", "id_table", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedIdTable = entityIdTableFromJSON(*IdTableArray); + if (!ExpectedIdTable) { + return ErrorBuilder::wrap(ExpectedIdTable.takeError()) + .context(ErrorMessages::ReadingFromField, "IdTable", "id_table") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getIdTable(Encoding) = std::move(*ExpectedIdTable); + } + + { + const Array *LinkageTableArray = RootObject.getArray("linkage_table"); + if (!LinkageTableArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "LinkageTable", "linkage_table", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedIdRange = + llvm::make_second_range(getEntities(getIdTable(Encoding))); + std::set ExpectedIds(ExpectedIdRange.begin(), + ExpectedIdRange.end()); + + // Move ExpectedIds in since linkageTableFromJSON consumes it to verify + // that the linkage table contains exactly the ids present in the IdTable. + auto ExpectedLinkageTable = + linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds)); + if (!ExpectedLinkageTable) { + return ErrorBuilder::wrap(ExpectedLinkageTable.takeError()) + .context(ErrorMessages::ReadingFromField, "LinkageTable", + "linkage_table") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getLinkageTable(Encoding) = std::move(*ExpectedLinkageTable); + } + + { + const Array *SummaryDataArray = RootObject.getArray("data"); + if (!SummaryDataArray) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "SummaryData entries", "data", "array") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + auto ExpectedEncodingSummaryDataMap = + encodingSummaryDataMapFromJSON(*SummaryDataArray); + if (!ExpectedEncodingSummaryDataMap) { + return ErrorBuilder::wrap(ExpectedEncodingSummaryDataMap.takeError()) + .context(ErrorMessages::ReadingFromField, "SummaryData entries", + "data") + .context(ErrorMessages::ReadingFromFile, "TUSummary", Path) + .build(); + } + + getData(Encoding) = std::move(*ExpectedEncodingSummaryDataMap); + } + + return std::move(Encoding); +} + +llvm::Error +JSONFormat::writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, + llvm::StringRef Path) { + Object RootObject; + + RootObject["tu_namespace"] = + buildNamespaceToJSON(getTUNamespace(SummaryEncoding)); + + RootObject["id_table"] = entityIdTableToJSON(getIdTable(SummaryEncoding)); + + RootObject["linkage_table"] = + linkageTableToJSON(getLinkageTable(SummaryEncoding)); + + RootObject["data"] = encodingSummaryDataMapToJSON(getData(SummaryEncoding)); + + if (auto Error = writeJSON(std::move(RootObject), Path)) { + return ErrorBuilder::wrap(std::move(Error)) + .context(ErrorMessages::WritingToFile, "TUSummary", Path) + .build(); + } + + return llvm::Error::success(); +} + +} // namespace clang::ssaf diff --git a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp index 7feb97d72ee2a..d734009b9d42c 100644 --- a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp +++ b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Registries/MockSerializationFormat.h" +#include "clang/Analysis/Scalable/EntityLinker/TUSummaryEncoding.h" #include "clang/Analysis/Scalable/Model/BuildNamespace.h" #include "clang/Analysis/Scalable/Model/EntityName.h" #include "clang/Analysis/Scalable/Model/SummaryName.h" @@ -154,3 +155,15 @@ llvm::Error MockSerializationFormat::writeTUSummary(const TUSummary &Summary, static SerializationFormatRegistry::Add RegisterFormat("MockSerializationFormat", "A serialization format for testing"); + +llvm::Expected +MockSerializationFormat::readTUSummaryEncoding(llvm::StringRef Path) { + llvm_unreachable( + "MockSerializationFormat does not support TUSummaryEncoding"); +} + +llvm::Error MockSerializationFormat::writeTUSummaryEncoding( + const TUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) { + llvm_unreachable( + "MockSerializationFormat does not support TUSummaryEncoding"); +} diff --git a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h index 918406c87afb3..7ec0de9216be0 100644 --- a/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h +++ b/clang/unittests/Analysis/Scalable/Registries/MockSerializationFormat.h @@ -27,6 +27,12 @@ class MockSerializationFormat final : public SerializationFormat { llvm::Error writeTUSummary(const TUSummary &Summary, llvm::StringRef Path) override; + llvm::Expected + readTUSummaryEncoding(llvm::StringRef Path) override; + + llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, + llvm::StringRef Path) override; + struct SpecialFileRepresentation { std::string MockRepresentation; }; diff --git a/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp index 612ca58419a12..c6098ed547529 100644 --- a/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp +++ b/clang/unittests/Analysis/Scalable/Serialization/JSONFormatTest/TUSummaryTest.cpp @@ -11,12 +11,15 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" #include "JSONFormatTest.h" + +#include "clang/Analysis/Scalable/EntityLinker/TUSummaryEncoding.h" #include "clang/Analysis/Scalable/Serialization/JSONFormat.h" +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" #include "llvm/Support/Registry.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" + #include #include @@ -232,247 +235,344 @@ static llvm::Registry::Add< "Format info for MismatchedEntitySummary"); // ============================================================================ -// JSONFormatTUSummaryTest Test Fixture +// TUSummaryOps - Parameterization support for TUSummary/TUSummaryEncoding tests // ============================================================================ -class JSONFormatTUSummaryTest : public JSONFormatTest { -protected: - llvm::Expected readTUSummaryFromFile(StringRef FileName) const { - PathString FilePath = makePath(FileName); +struct TUSummaryOps { + std::string Name; + std::function ReadFromFile; + std::function WriteEmpty; + std::function + ReadWriteRoundTrip; +}; - return JSONFormat().readTUSummary(FilePath); - } +static TUSummaryOps makeTUSummaryOps() { + return TUSummaryOps{ + "Resolved", + [](llvm::StringRef FilePath) -> llvm::Error { + auto Result = JSONFormat().readTUSummary(FilePath); + return Result ? llvm::Error::success() : Result.takeError(); + }, + [](llvm::StringRef FilePath) -> llvm::Error { + TUSummary S( + BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); + return JSONFormat().writeTUSummary(S, FilePath); + }, + [](llvm::StringRef InputFilePath, + llvm::StringRef OutputFilePath) -> llvm::Error { + auto ExpectedS = JSONFormat().readTUSummary(InputFilePath); + if (!ExpectedS) + return ExpectedS.takeError(); + return JSONFormat().writeTUSummary(*ExpectedS, OutputFilePath); + }}; +} + +static TUSummaryOps makeTUSummaryEncodingOps() { + return TUSummaryOps{ + "Encoding", + [](llvm::StringRef FilePath) -> llvm::Error { + auto Result = JSONFormat().readTUSummaryEncoding(FilePath); + return Result ? llvm::Error::success() : Result.takeError(); + }, + [](llvm::StringRef FilePath) -> llvm::Error { + TUSummaryEncoding E( + BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); + return JSONFormat().writeTUSummaryEncoding(E, FilePath); + }, + [](llvm::StringRef InputFilePath, + llvm::StringRef OutputFilePath) -> llvm::Error { + auto ExpectedE = JSONFormat().readTUSummaryEncoding(InputFilePath); + if (!ExpectedE) + return ExpectedE.takeError(); + return JSONFormat().writeTUSummaryEncoding(*ExpectedE, OutputFilePath); + }}; +} - llvm::Expected - readTUSummaryFromString(StringRef JSON, - StringRef FileName = "test.json") const { +// ============================================================================ +// TUSummaryTest Test Fixture +// ============================================================================ + +class TUSummaryTest : public JSONFormatTest, + public ::testing::WithParamInterface { +protected: + llvm::Error readFromString(StringRef JSON, + StringRef FileName = "test.json") const { auto ExpectedFilePath = writeJSON(JSON, FileName); if (!ExpectedFilePath) return ExpectedFilePath.takeError(); - - return readTUSummaryFromFile(FileName); + return GetParam().ReadFromFile(*ExpectedFilePath); } - llvm::Error writeTUSummary(const TUSummary &Summary, - StringRef FileName) const { - PathString FilePath = makePath(FileName); - - return JSONFormat().writeTUSummary(Summary, FilePath); + llvm::Error readFromFile(StringRef FileName) const { + return GetParam().ReadFromFile(makePath(FileName)); } - static llvm::Error normalizeIDTable(json::Array &IDTable) { - for (const auto &[Index, Entry] : llvm::enumerate(IDTable)) { - const auto *EntryObj = Entry.getAsObject(); - if (!EntryObj) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: id_table entry at index %zu " - "is not an object", - Index); - } + llvm::Error writeEmpty(StringRef FileName) const { + return GetParam().WriteEmpty(makePath(FileName)); + } - const auto *IDValue = EntryObj->get("id"); - if (!IDValue) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: id_table entry at index %zu " - "does not contain an 'id' field", - Index); - } + llvm::Error readWriteRoundTrip(StringRef InputFileName, + StringRef OutputFileName) const { + return GetParam().ReadWriteRoundTrip(makePath(InputFileName), + makePath(OutputFileName)); + } - if (!IDValue->getAsUINT64()) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: id_table entry at index %zu " - "does not contain a valid 'id' uint64_t field", - Index); - } - } + void readWriteCompare(StringRef JSON) const; +}; - // Safe to dereference: all entries were validated above. - llvm::sort(IDTable, [](const json::Value &A, const json::Value &B) { - return *A.getAsObject()->get("id")->getAsUINT64() < - *B.getAsObject()->get("id")->getAsUINT64(); +INSTANTIATE_TEST_SUITE_P( + JSONFormat, TUSummaryTest, + ::testing::Values(makeTUSummaryOps(), makeTUSummaryEncodingOps()), + [](const ::testing::TestParamInfo &Info) { + return Info.param.Name; }); - return llvm::Error::success(); - } - - static llvm::Error normalizeLinkageTable(json::Array &LinkageTable) { - for (const auto &[Index, Entry] : llvm::enumerate(LinkageTable)) { - const auto *EntryObj = Entry.getAsObject(); - if (!EntryObj) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: linkage_table entry at index " - "%zu is not an object", - Index); - } - - const auto *IDValue = EntryObj->get("id"); - if (!IDValue) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: linkage_table entry at index " - "%zu does not contain an 'id' field", - Index); - } +// ============================================================================ +// TUSummary JSON Normalization Helpers +// ============================================================================ - if (!IDValue->getAsUINT64()) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: linkage_table entry at index " - "%zu does not contain a valid 'id' uint64_t field", - Index); - } +static llvm::Error normalizeIDTable(json::Array &IDTable) { + for (const auto &[Index, Entry] : llvm::enumerate(IDTable)) { + const auto *EntryObj = Entry.getAsObject(); + if (!EntryObj) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: id_table entry at index %zu " + "is not an object", + Index); } - // Safe to dereference: all entries were validated above. - llvm::sort(LinkageTable, [](const json::Value &A, const json::Value &B) { - return *A.getAsObject()->get("id")->getAsUINT64() < - *B.getAsObject()->get("id")->getAsUINT64(); - }); + const auto *IDValue = EntryObj->get("id"); + if (!IDValue) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: id_table entry at index %zu " + "does not contain an 'id' field", + Index); + } - return llvm::Error::success(); + if (!IDValue->getAsUINT64()) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: id_table entry at index %zu " + "does not contain a valid 'id' uint64_t field", + Index); + } } - static llvm::Error normalizeSummaryData(json::Array &SummaryData, - size_t DataIndex) { - for (const auto &[SummaryIndex, SummaryEntry] : - llvm::enumerate(SummaryData)) { - const auto *SummaryEntryObj = SummaryEntry.getAsObject(); - if (!SummaryEntryObj) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu, " - "summary_data entry at index %zu is not an object", - DataIndex, SummaryIndex); - } + // Safe to dereference: all entries were validated above. + llvm::sort(IDTable, [](const json::Value &A, const json::Value &B) { + return *A.getAsObject()->get("id")->getAsUINT64() < + *B.getAsObject()->get("id")->getAsUINT64(); + }); - const auto *EntityIDValue = SummaryEntryObj->get("entity_id"); - if (!EntityIDValue) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu, " - "summary_data entry at index %zu does not contain an " - "'entity_id' field", - DataIndex, SummaryIndex); - } + return llvm::Error::success(); +} - if (!EntityIDValue->getAsUINT64()) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu, " - "summary_data entry at index %zu does not contain a valid " - "'entity_id' uint64_t field", - DataIndex, SummaryIndex); - } +static llvm::Error normalizeLinkageTable(json::Array &LinkageTable) { + for (const auto &[Index, Entry] : llvm::enumerate(LinkageTable)) { + const auto *EntryObj = Entry.getAsObject(); + if (!EntryObj) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: linkage_table entry at index " + "%zu is not an object", + Index); } - // Safe to dereference: all entries were validated above. - llvm::sort(SummaryData, [](const json::Value &A, const json::Value &B) { - return *A.getAsObject()->get("entity_id")->getAsUINT64() < - *B.getAsObject()->get("entity_id")->getAsUINT64(); - }); + const auto *IDValue = EntryObj->get("id"); + if (!IDValue) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: linkage_table entry at index " + "%zu does not contain an 'id' field", + Index); + } - return llvm::Error::success(); + if (!IDValue->getAsUINT64()) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: linkage_table entry at index " + "%zu does not contain a valid 'id' uint64_t field", + Index); + } } - static llvm::Error normalizeData(json::Array &Data) { - for (const auto &[DataIndex, DataEntry] : llvm::enumerate(Data)) { - auto *DataEntryObj = DataEntry.getAsObject(); - if (!DataEntryObj) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu " - "is not an object", - DataIndex); - } - - if (!DataEntryObj->getString("summary_name")) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu " - "does not contain a 'summary_name' string field", - DataIndex); - } + // Safe to dereference: all entries were validated above. + llvm::sort(LinkageTable, [](const json::Value &A, const json::Value &B) { + return *A.getAsObject()->get("id")->getAsUINT64() < + *B.getAsObject()->get("id")->getAsUINT64(); + }); - auto *SummaryData = DataEntryObj->getArray("summary_data"); - if (!SummaryData) { - return createStringError( - inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: data entry at index %zu " - "does not contain a 'summary_data' array field", - DataIndex); - } + return llvm::Error::success(); +} - if (auto Err = normalizeSummaryData(*SummaryData, DataIndex)) { - return Err; - } +static llvm::Error normalizeSummaryData(json::Array &SummaryData, + size_t DataIndex) { + for (const auto &[SummaryIndex, SummaryEntry] : + llvm::enumerate(SummaryData)) { + const auto *SummaryEntryObj = SummaryEntry.getAsObject(); + if (!SummaryEntryObj) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: data entry at index %zu, " + "summary_data entry at index %zu is not an object", + DataIndex, SummaryIndex); } - // Safe to dereference: all entries were validated above. - llvm::sort(Data, [](const json::Value &A, const json::Value &B) { - return *A.getAsObject()->getString("summary_name") < - *B.getAsObject()->getString("summary_name"); - }); + const auto *EntityIDValue = SummaryEntryObj->get("entity_id"); + if (!EntityIDValue) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: data entry at index %zu, " + "summary_data entry at index %zu does not contain an " + "'entity_id' field", + DataIndex, SummaryIndex); + } - return llvm::Error::success(); + if (!EntityIDValue->getAsUINT64()) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: data entry at index %zu, " + "summary_data entry at index %zu does not contain a valid " + "'entity_id' uint64_t field", + DataIndex, SummaryIndex); + } } - static Expected normalizeTUSummaryJSON(json::Value Val) { - auto *Obj = Val.getAsObject(); - if (!Obj) { + // Safe to dereference: all entries were validated above. + llvm::sort(SummaryData, [](const json::Value &A, const json::Value &B) { + return *A.getAsObject()->get("entity_id")->getAsUINT64() < + *B.getAsObject()->get("entity_id")->getAsUINT64(); + }); + + return llvm::Error::success(); +} + +static llvm::Error normalizeData(json::Array &Data) { + for (const auto &[DataIndex, DataEntry] : llvm::enumerate(Data)) { + auto *DataEntryObj = DataEntry.getAsObject(); + if (!DataEntryObj) { return createStringError( inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: expected an object"); + "Cannot normalize TUSummary JSON: data entry at index %zu " + "is not an object", + DataIndex); } - auto *IDTable = Obj->getArray("id_table"); - if (!IDTable) { - return createStringError(inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: 'id_table' " - "field is either missing or has the wrong type"); - } - if (auto Err = normalizeIDTable(*IDTable)) { - return std::move(Err); + if (!DataEntryObj->getString("summary_name")) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: data entry at index %zu " + "does not contain a 'summary_name' string field", + DataIndex); } - auto *LinkageTable = Obj->getArray("linkage_table"); - if (!LinkageTable) { + auto *SummaryData = DataEntryObj->getArray("summary_data"); + if (!SummaryData) { return createStringError( inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: 'linkage_table' " - "field is either missing or has the wrong type"); - } - if (auto Err = normalizeLinkageTable(*LinkageTable)) { - return std::move(Err); + "Cannot normalize TUSummary JSON: data entry at index %zu " + "does not contain a 'summary_data' array field", + DataIndex); } - auto *Data = Obj->getArray("data"); - if (!Data) { - return createStringError(inconvertibleErrorCode(), - "Cannot normalize TUSummary JSON: 'data' " - "field is either missing or has the wrong type"); - } - if (auto Err = normalizeData(*Data)) { - return std::move(Err); + if (auto Err = normalizeSummaryData(*SummaryData, DataIndex)) { + return Err; } + } + + // Safe to dereference: all entries were validated above. + llvm::sort(Data, [](const json::Value &A, const json::Value &B) { + return *A.getAsObject()->getString("summary_name") < + *B.getAsObject()->getString("summary_name"); + }); - return Val; + return llvm::Error::success(); +} + +static Expected normalizeTUSummaryJSON(json::Value Val) { + auto *Obj = Val.getAsObject(); + if (!Obj) { + return createStringError( + inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: expected an object"); } - // Compare two TUSummary JSON values with normalization. - static Expected compareTUSummaryJSON(json::Value A, json::Value B) { - auto ExpectedNormalizedA = normalizeTUSummaryJSON(std::move(A)); - if (!ExpectedNormalizedA) - return ExpectedNormalizedA.takeError(); + auto *IDTable = Obj->getArray("id_table"); + if (!IDTable) { + return createStringError(inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: 'id_table' " + "field is either missing or has the wrong type"); + } + if (auto Err = normalizeIDTable(*IDTable)) { + return std::move(Err); + } - auto ExpectedNormalizedB = normalizeTUSummaryJSON(std::move(B)); - if (!ExpectedNormalizedB) - return ExpectedNormalizedB.takeError(); + auto *LinkageTable = Obj->getArray("linkage_table"); + if (!LinkageTable) { + return createStringError(inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: 'linkage_table' " + "field is either missing or has the wrong type"); + } + if (auto Err = normalizeLinkageTable(*LinkageTable)) { + return std::move(Err); + } + + auto *Data = Obj->getArray("data"); + if (!Data) { + return createStringError(inconvertibleErrorCode(), + "Cannot normalize TUSummary JSON: 'data' " + "field is either missing or has the wrong type"); + } + if (auto Err = normalizeData(*Data)) { + return std::move(Err); + } + + return Val; +} + +// Compare two TUSummary JSON values with normalization. +static Expected compareTUSummaryJSON(json::Value A, json::Value B) { + auto ExpectedNormalizedA = normalizeTUSummaryJSON(std::move(A)); + if (!ExpectedNormalizedA) + return ExpectedNormalizedA.takeError(); + + auto ExpectedNormalizedB = normalizeTUSummaryJSON(std::move(B)); + if (!ExpectedNormalizedB) + return ExpectedNormalizedB.takeError(); + + return *ExpectedNormalizedA == *ExpectedNormalizedB; +} + +// ============================================================================ +// JSONFormatTUSummaryTest Test Fixture +// ============================================================================ + +class JSONFormatTUSummaryTest : public JSONFormatTest { +protected: + llvm::Expected readTUSummaryFromFile(StringRef FileName) const { + PathString FilePath = makePath(FileName); + + return JSONFormat().readTUSummary(FilePath); + } + + llvm::Expected + readTUSummaryFromString(StringRef JSON, + StringRef FileName = "test.json") const { + auto ExpectedFilePath = writeJSON(JSON, FileName); + if (!ExpectedFilePath) + return ExpectedFilePath.takeError(); - return *ExpectedNormalizedA == *ExpectedNormalizedB; + return readTUSummaryFromFile(FileName); + } + + llvm::Error writeTUSummary(const TUSummary &Summary, + StringRef FileName) const { + PathString FilePath = makePath(FileName); + + return JSONFormat().writeTUSummary(Summary, FilePath); } void readWriteCompareTUSummary(StringRef JSON) const { @@ -518,48 +618,86 @@ class JSONFormatTUSummaryTest : public JSONFormatTest { } }; +void TUSummaryTest::readWriteCompare(StringRef JSON) const { + const PathString InputFileName("input.json"); + const PathString OutputFileName("output.json"); + + auto ExpectedInputFilePath = writeJSON(JSON, InputFileName); + ASSERT_THAT_EXPECTED(ExpectedInputFilePath, Succeeded()); + + ASSERT_THAT_ERROR(readWriteRoundTrip(InputFileName, OutputFileName), + Succeeded()); + + auto ExpectedInputJSON = readJSONFromFile(InputFileName); + ASSERT_THAT_EXPECTED(ExpectedInputJSON, Succeeded()); + auto ExpectedOutputJSON = readJSONFromFile(OutputFileName); + ASSERT_THAT_EXPECTED(ExpectedOutputJSON, Succeeded()); + + auto ExpectedComparisonResult = + compareTUSummaryJSON(*ExpectedInputJSON, *ExpectedOutputJSON); + ASSERT_THAT_EXPECTED(ExpectedComparisonResult, Succeeded()) + << "Failed to normalize JSON for comparison"; + + if (!*ExpectedComparisonResult) { + auto ExpectedNormalizedInput = normalizeTUSummaryJSON(*ExpectedInputJSON); + auto ExpectedNormalizedOutput = normalizeTUSummaryJSON(*ExpectedOutputJSON); + FAIL() << "Serialization is broken: input JSON is different from output " + "json\n" + << "Input: " + << (ExpectedNormalizedInput + ? llvm::formatv("{0:2}", *ExpectedNormalizedInput).str() + : "normalization failed") + << "\n" + << "Output: " + << (ExpectedNormalizedOutput + ? llvm::formatv("{0:2}", *ExpectedNormalizedOutput).str() + : "normalization failed"); + } +} + // ============================================================================ // readJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, NonexistentFile) { - auto Result = readTUSummaryFromFile("nonexistent.json"); +TEST_P(TUSummaryTest, NonexistentFile) { + auto Result = readFromFile("nonexistent.json"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"), - HasSubstr("file does not exist")))); + EXPECT_THAT_ERROR(std::move(Result), + FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"), + HasSubstr("file does not exist")))); } -TEST_F(JSONFormatTUSummaryTest, PathIsDirectory) { +TEST_P(TUSummaryTest, PathIsDirectory) { PathString DirName("test_directory.json"); auto ExpectedDirPath = makeDirectory(DirName); ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded()); - auto Result = readTUSummaryFromFile(DirName); + auto Result = readFromFile(DirName); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"), HasSubstr("path is a directory, not a file")))); } -TEST_F(JSONFormatTUSummaryTest, NotJsonExtension) { +TEST_P(TUSummaryTest, NotJsonExtension) { PathString FileName("test.txt"); auto ExpectedFilePath = writeJSON("{}", FileName); ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded()); - auto Result = readTUSummaryFromFile(FileName); + auto Result = readFromFile(FileName); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read file"), - HasSubstr("file does not end with '.json' extension")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("failed to read file"), + HasSubstr("file does not end with '.json' extension")))); } -TEST_F(JSONFormatTUSummaryTest, BrokenSymlink) { +TEST_P(TUSummaryTest, BrokenSymlink) { #ifdef _WIN32 GTEST_SKIP() << "Symlink model differs on Windows"; #endif @@ -569,14 +707,14 @@ TEST_F(JSONFormatTUSummaryTest, BrokenSymlink) { makeSymlink("nonexistent_target.json", "broken_symlink.json"); ASSERT_THAT_EXPECTED(ExpectedSymlinkPath, Succeeded()); - auto Result = readTUSummaryFromFile(*ExpectedSymlinkPath); + auto Result = readFromFile(*ExpectedSymlinkPath); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read file")))); + EXPECT_THAT_ERROR(std::move(Result), + FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"), + HasSubstr("failed to read file")))); } -TEST_F(JSONFormatTUSummaryTest, NoReadPermission) { +TEST_P(TUSummaryTest, NoReadPermission) { if (!permissionsAreEnforced()) { GTEST_SKIP() << "File permission checks are not enforced in this " "environment"; @@ -600,40 +738,42 @@ TEST_F(JSONFormatTUSummaryTest, NoReadPermission) { sys::fs::perms::owner_exe); ASSERT_THAT_ERROR(std::move(PermError), Succeeded()); - auto Result = readTUSummaryFromFile(FileName); + auto Result = readFromFile(FileName); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read file")))); + EXPECT_THAT_ERROR(std::move(Result), + FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"), + HasSubstr("failed to read file")))); // Restore permissions for cleanup auto RestoreError = setPermission(FileName, sys::fs::perms::all_all); EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded()); } -TEST_F(JSONFormatTUSummaryTest, InvalidSyntax) { - auto Result = readTUSummaryFromString("{ invalid json }"); +TEST_P(TUSummaryTest, InvalidSyntax) { + auto Result = readFromString("{ invalid json }"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), - HasSubstr("Expected object key")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("Expected object key")))); } -TEST_F(JSONFormatTUSummaryTest, NotObject) { - auto Result = readTUSummaryFromString("[]"); +TEST_P(TUSummaryTest, NotObject) { + auto Result = readFromString("[]"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read TUSummary"), - HasSubstr("expected JSON object")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage(AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("failed to read TUSummary"), + HasSubstr("expected JSON object")))); } // ============================================================================ // JSONFormat::entityLinkageFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryLinkageMissingType) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableEntryLinkageMissingType) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -648,8 +788,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryLinkageMissingType) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading LinkageTable from field 'linkage_table'"), @@ -659,8 +799,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryLinkageMissingType) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryLinkageInvalidType) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableEntryLinkageInvalidType) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -675,22 +815,23 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryLinkageInvalidType) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, - FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading LinkageTable from field 'linkage_table'"), - HasSubstr("reading LinkageTable entry from index '0'"), - HasSubstr("reading EntityLinkage from field 'linkage'"), - HasSubstr("invalid 'type' EntityLinkageType value 'invalid_type'")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading LinkageTable from field 'linkage_table'"), + HasSubstr("reading LinkageTable entry from index '0'"), + HasSubstr("reading EntityLinkage from field 'linkage'"), + HasSubstr("invalid EntityLinkageType value 'invalid_type' for " + "field 'type'")))); } // ============================================================================ // JSONFormat::linkageTableEntryFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingId) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableEntryMissingId) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -704,8 +845,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingId) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading LinkageTable from field 'linkage_table'"), @@ -714,8 +855,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingId) { HasSubstr("expected JSON number (unsigned 64-bit integer)")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryIdNotUInt64) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableEntryIdNotUInt64) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -730,8 +871,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryIdNotUInt64) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading LinkageTable from field 'linkage_table'"), @@ -740,8 +881,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryIdNotUInt64) { HasSubstr("expected JSON number (unsigned 64-bit integer)")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingLinkage) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableEntryMissingLinkage) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -755,8 +896,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingLinkage) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading LinkageTable from field 'linkage_table'"), @@ -769,8 +910,8 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableEntryMissingLinkage) { // JSONFormat::linkageTableFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, LinkageTableNotArray) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableNotArray) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -780,16 +921,16 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableNotArray) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("failed to read LinkageTable from field 'linkage_table'"), HasSubstr("expected JSON array")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableElementNotObject) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableElementNotObject) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -799,16 +940,17 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableElementNotObject) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading LinkageTable from field 'linkage_table'"), - HasSubstr("failed to read LinkageTable entry from index '0'"), - HasSubstr("expected JSON object")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading LinkageTable from field 'linkage_table'"), + HasSubstr("failed to read LinkageTable entry from index '0'"), + HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableExtraId) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableExtraId) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -823,17 +965,18 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableExtraId) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading LinkageTable from field 'linkage_table'"), - HasSubstr("reading LinkageTable entry from index '0'"), - HasSubstr("failed to deserialize LinkageTable"), - HasSubstr("extra 'EntityId(0)' not present in IdTable")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading LinkageTable from field 'linkage_table'"), + HasSubstr("reading LinkageTable entry from index '0'"), + HasSubstr("failed to deserialize LinkageTable"), + HasSubstr("extra 'EntityId(0)' not present in IdTable")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableMissingId) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableMissingId) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -857,16 +1000,17 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableMissingId) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading LinkageTable from field 'linkage_table'"), - HasSubstr("failed to deserialize LinkageTable"), - HasSubstr("missing 'EntityId(0)' present in IdTable")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading LinkageTable from field 'linkage_table'"), + HasSubstr("failed to deserialize LinkageTable"), + HasSubstr("missing 'EntityId(0)' present in IdTable")))); } -TEST_F(JSONFormatTUSummaryTest, LinkageTableDuplicateId) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, LinkageTableDuplicateId) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -899,20 +1043,21 @@ TEST_F(JSONFormatTUSummaryTest, LinkageTableDuplicateId) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading LinkageTable from field 'linkage_table'"), - HasSubstr("failed to insert LinkageTable entry at index '1'"), - HasSubstr("encountered duplicate 'EntityId(0)'")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading LinkageTable from field 'linkage_table'"), + HasSubstr("failed to insert LinkageTable entry at index '1'"), + HasSubstr("encountered duplicate 'EntityId(0)'")))); } // ============================================================================ // JSONFormat::buildNamespaceKindFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, InvalidKind) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, InvalidKind) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "invalid_kind", "name": "test.cpp" @@ -922,22 +1067,22 @@ TEST_F(JSONFormatTUSummaryTest, InvalidKind) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, - FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading BuildNamespace from field 'tu_namespace'"), - HasSubstr("reading BuildNamespaceKind from field 'kind'"), - HasSubstr( - "invalid 'kind' BuildNamespaceKind value 'invalid_kind'")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading BuildNamespace from field 'tu_namespace'"), + HasSubstr("reading BuildNamespaceKind from field 'kind'"), + HasSubstr("invalid BuildNamespaceKind value 'invalid_kind' for " + "field 'kind'")))); } // ============================================================================ // JSONFormat::buildNamespaceFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, MissingKind) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingKind) { + auto Result = readFromString(R"({ "tu_namespace": { "name": "test.cpp" }, @@ -946,8 +1091,8 @@ TEST_F(JSONFormatTUSummaryTest, MissingKind) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading BuildNamespace from field 'tu_namespace'"), @@ -955,8 +1100,8 @@ TEST_F(JSONFormatTUSummaryTest, MissingKind) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, MissingName) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingName) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit" }, @@ -965,8 +1110,8 @@ TEST_F(JSONFormatTUSummaryTest, MissingName) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading BuildNamespace from field 'tu_namespace'"), @@ -978,8 +1123,8 @@ TEST_F(JSONFormatTUSummaryTest, MissingName) { // JSONFormat::nestedBuildNamespaceFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, NamespaceElementNotObject) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, NamespaceElementNotObject) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1003,8 +1148,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementNotObject) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1015,8 +1160,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementNotObject) { HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingKind) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, NamespaceElementMissingKind) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1044,8 +1189,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingKind) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1057,8 +1202,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingKind) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, NamespaceElementInvalidKind) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, NamespaceElementInvalidKind) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1087,8 +1232,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementInvalidKind) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1097,12 +1242,12 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementInvalidKind) { HasSubstr("reading NestedBuildNamespace from field 'namespace'"), HasSubstr("reading BuildNamespace from index '0'"), HasSubstr("reading BuildNamespaceKind from field 'kind'"), - HasSubstr( - "invalid 'kind' BuildNamespaceKind value 'invalid_kind'")))); + HasSubstr("invalid BuildNamespaceKind value 'invalid_kind' for field " + "'kind'")))); } -TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingName) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, NamespaceElementMissingName) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1130,8 +1275,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingName) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1147,8 +1292,8 @@ TEST_F(JSONFormatTUSummaryTest, NamespaceElementMissingName) { // JSONFormat::entityNameFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, EntityNameMissingUSR) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityNameMissingUSR) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1171,9 +1316,9 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingUSR) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage( - AllOf(HasSubstr("reading TUSummary from file"), + EXPECT_THAT_ERROR(std::move(Result), + FailedWithMessage(AllOf( + HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), HasSubstr("reading EntityIdTable entry from index '0'"), HasSubstr("reading EntityName from field 'name'"), @@ -1181,8 +1326,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingUSR) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, EntityNameMissingSuffix) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityNameMissingSuffix) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1205,9 +1350,9 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingSuffix) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage( - AllOf(HasSubstr("reading TUSummary from file"), + EXPECT_THAT_ERROR(std::move(Result), + FailedWithMessage(AllOf( + HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), HasSubstr("reading EntityIdTable entry from index '0'"), HasSubstr("reading EntityName from field 'name'"), @@ -1215,8 +1360,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingSuffix) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, EntityNameMissingNamespace) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityNameMissingNamespace) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1239,8 +1384,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingNamespace) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1255,8 +1400,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityNameMissingNamespace) { // JSONFormat::entityIdTableEntryFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingID) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, IDTableEntryMissingID) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1274,8 +1419,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingID) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1284,8 +1429,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingID) { HasSubstr("expected JSON number (unsigned 64-bit integer)")))); } -TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingName) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, IDTableEntryMissingName) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1304,17 +1449,18 @@ TEST_F(JSONFormatTUSummaryTest, IDTableEntryMissingName) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading IdTable from field 'id_table'"), - HasSubstr("reading EntityIdTable entry from index '0'"), - HasSubstr("failed to read EntityName from field 'name'"), - HasSubstr("expected JSON object")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading IdTable from field 'id_table'"), + HasSubstr("reading EntityIdTable entry from index '0'"), + HasSubstr("failed to read EntityName from field 'name'"), + HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, IDTableEntryIDNotUInt64) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, IDTableEntryIDNotUInt64) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1333,8 +1479,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableEntryIDNotUInt64) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1347,8 +1493,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableEntryIDNotUInt64) { // JSONFormat::entityIdTableFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, IDTableNotArray) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, IDTableNotArray) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1358,15 +1504,16 @@ TEST_F(JSONFormatTUSummaryTest, IDTableNotArray) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read IdTable from field 'id_table'"), - HasSubstr("expected JSON array")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("failed to read IdTable from field 'id_table'"), + HasSubstr("expected JSON array")))); } -TEST_F(JSONFormatTUSummaryTest, IDTableElementNotObject) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, IDTableElementNotObject) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1376,8 +1523,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableElementNotObject) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1385,8 +1532,8 @@ TEST_F(JSONFormatTUSummaryTest, IDTableElementNotObject) { HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, DuplicateEntity) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DuplicateEntity) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1432,8 +1579,8 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateEntity) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage( AllOf(HasSubstr("reading TUSummary from file"), HasSubstr("reading IdTable from field 'id_table'"), @@ -1442,7 +1589,7 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateEntity) { } // ============================================================================ -// JSONFormat::entitySummaryFromJSON() Error Tests +// JSONFormat::entitySummaryFromJSON() / encodingDataMapEntryFromJSON() Tests // ============================================================================ TEST_F(JSONFormatTUSummaryTest, ReadEntitySummaryNoFormatInfo) { @@ -1757,8 +1904,8 @@ TEST_F(JSONFormatTUSummaryTest, // JSONFormat::entityDataMapEntryFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntityID) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityDataMissingEntityID) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1777,8 +1924,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntityID) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -1789,8 +1936,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntityID) { HasSubstr("expected JSON number (unsigned 64-bit integer)")))); } -TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntitySummary) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityDataMissingEntitySummary) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1809,8 +1956,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntitySummary) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -1821,8 +1968,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataMissingEntitySummary) { HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, EntityIDNotUInt64) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityIDNotUInt64) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1842,8 +1989,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityIDNotUInt64) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -1973,8 +2120,8 @@ TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryMismatchedSummaryName) { // JSONFormat::entityDataMapFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, EntityDataElementNotObject) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, EntityDataElementNotObject) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -1989,8 +2136,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataElementNotObject) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -2000,8 +2147,8 @@ TEST_F(JSONFormatTUSummaryTest, EntityDataElementNotObject) { HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, DuplicateEntityIdInDataMap) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DuplicateEntityIdInDataMap) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2045,8 +2192,8 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateEntityIdInDataMap) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -2060,8 +2207,8 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateEntityIdInDataMap) { // JSONFormat::summaryDataMapEntryFromJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, DataEntryMissingSummaryName) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DataEntryMissingSummaryName) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2075,8 +2222,8 @@ TEST_F(JSONFormatTUSummaryTest, DataEntryMissingSummaryName) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -2085,8 +2232,8 @@ TEST_F(JSONFormatTUSummaryTest, DataEntryMissingSummaryName) { HasSubstr("expected JSON string")))); } -TEST_F(JSONFormatTUSummaryTest, DataEntryMissingData) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DataEntryMissingData) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2100,8 +2247,8 @@ TEST_F(JSONFormatTUSummaryTest, DataEntryMissingData) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -2112,11 +2259,11 @@ TEST_F(JSONFormatTUSummaryTest, DataEntryMissingData) { } // ============================================================================ -// JSONFormat::summaryDataMapFromJSON() Error Tests +// JSONFormat::summaryDataMapFromJSON() / encodingSummaryDataMapFromJSON() Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, DataNotArray) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DataNotArray) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2126,16 +2273,16 @@ TEST_F(JSONFormatTUSummaryTest, DataNotArray) { "data": {} })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("failed to read SummaryData entries from field 'data'"), HasSubstr("expected JSON array")))); } -TEST_F(JSONFormatTUSummaryTest, DataElementNotObject) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DataElementNotObject) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2145,16 +2292,17 @@ TEST_F(JSONFormatTUSummaryTest, DataElementNotObject) { "data": ["invalid"] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("reading SummaryData entries from field 'data'"), - HasSubstr("failed to read SummaryData entry from index '0'"), - HasSubstr("expected JSON object")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("reading SummaryData entries from field 'data'"), + HasSubstr("failed to read SummaryData entry from index '0'"), + HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, DuplicateSummaryName) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, DuplicateSummaryName) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2173,8 +2321,8 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateSummaryName) { ] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("reading SummaryData entries from field 'data'"), @@ -2184,26 +2332,26 @@ TEST_F(JSONFormatTUSummaryTest, DuplicateSummaryName) { } // ============================================================================ -// JSONFormat::readTUSummary() Error Tests +// JSONFormat::readTUSummary() / readTUSummaryEncoding() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, MissingTUNamespace) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingTUNamespace) { + auto Result = readFromString(R"({ "id_table": [], "linkage_table": [], "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("failed to read BuildNamespace from field 'tu_namespace'"), HasSubstr("expected JSON object")))); } -TEST_F(JSONFormatTUSummaryTest, MissingIDTable) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingIDTable) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2211,15 +2359,16 @@ TEST_F(JSONFormatTUSummaryTest, MissingIDTable) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, FailedWithMessage(AllOf( - HasSubstr("reading TUSummary from file"), - HasSubstr("failed to read IdTable from field 'id_table'"), - HasSubstr("expected JSON array")))); + EXPECT_THAT_ERROR( + std::move(Result), + FailedWithMessage( + AllOf(HasSubstr("reading TUSummary from file"), + HasSubstr("failed to read IdTable from field 'id_table'"), + HasSubstr("expected JSON array")))); } -TEST_F(JSONFormatTUSummaryTest, MissingLinkageTable) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingLinkageTable) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2228,16 +2377,16 @@ TEST_F(JSONFormatTUSummaryTest, MissingLinkageTable) { "data": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("failed to read LinkageTable from field 'linkage_table'"), HasSubstr("expected JSON array")))); } -TEST_F(JSONFormatTUSummaryTest, MissingData) { - auto Result = readTUSummaryFromString(R"({ +TEST_P(TUSummaryTest, MissingData) { + auto Result = readFromString(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2246,8 +2395,8 @@ TEST_F(JSONFormatTUSummaryTest, MissingData) { "linkage_table": [] })"); - EXPECT_THAT_EXPECTED( - Result, + EXPECT_THAT_ERROR( + std::move(Result), FailedWithMessage(AllOf( HasSubstr("reading TUSummary from file"), HasSubstr("failed to read SummaryData entries from field 'data'"), @@ -2258,17 +2407,13 @@ TEST_F(JSONFormatTUSummaryTest, MissingData) { // JSONFormat::writeJSON() Error Tests // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, WriteFileAlreadyExists) { +TEST_P(TUSummaryTest, WriteFileAlreadyExists) { PathString FileName("existing.json"); auto ExpectedFilePath = writeJSON("{}", FileName); ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded()); - TUSummary Summary( - BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); - - // Try to write to the same path - auto Result = writeTUSummary(Summary, FileName); + auto Result = writeEmpty(FileName); EXPECT_THAT_ERROR( std::move(Result), @@ -2277,13 +2422,10 @@ TEST_F(JSONFormatTUSummaryTest, WriteFileAlreadyExists) { HasSubstr("file already exists")))); } -TEST_F(JSONFormatTUSummaryTest, WriteParentDirectoryNotFound) { +TEST_P(TUSummaryTest, WriteParentDirectoryNotFound) { PathString FilePath = makePath("nonexistent-dir", "test.json"); - TUSummary Summary( - BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); - - auto Result = JSONFormat().writeTUSummary(Summary, FilePath); + auto Result = GetParam().WriteEmpty(FilePath); EXPECT_THAT_ERROR( std::move(Result), @@ -2292,11 +2434,8 @@ TEST_F(JSONFormatTUSummaryTest, WriteParentDirectoryNotFound) { HasSubstr("parent directory does not exist")))); } -TEST_F(JSONFormatTUSummaryTest, WriteNotJsonExtension) { - TUSummary Summary( - BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); - - auto Result = writeTUSummary(Summary, "test.txt"); +TEST_P(TUSummaryTest, WriteNotJsonExtension) { + auto Result = writeEmpty("test.txt"); EXPECT_THAT_ERROR( std::move(Result), @@ -2306,7 +2445,7 @@ TEST_F(JSONFormatTUSummaryTest, WriteNotJsonExtension) { HasSubstr("file does not end with '.json' extension")))); } -TEST_F(JSONFormatTUSummaryTest, WriteStreamOpenFailure) { +TEST_P(TUSummaryTest, WriteStreamOpenFailure) { if (!permissionsAreEnforced()) { GTEST_SKIP() << "File permission checks are not enforced in this " "environment"; @@ -2323,10 +2462,7 @@ TEST_F(JSONFormatTUSummaryTest, WriteStreamOpenFailure) { PathString FilePath = makePath(DirName, "test.json"); - TUSummary Summary( - BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp")); - - auto Result = JSONFormat().writeTUSummary(Summary, FilePath); + auto Result = GetParam().WriteEmpty(FilePath); EXPECT_THAT_ERROR( std::move(Result), @@ -2339,7 +2475,7 @@ TEST_F(JSONFormatTUSummaryTest, WriteStreamOpenFailure) { } // ============================================================================ -// JSONFormat::writeTUSummary() Error Tests +// JSONFormat::writeTUSummary() Error Tests (TUSummary-only) // ============================================================================ TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryNoFormatInfo) { @@ -2376,8 +2512,8 @@ TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryNoFormatInfo) { // Round-Trip Tests - Serialization Verification // ============================================================================ -TEST_F(JSONFormatTUSummaryTest, RoundTripEmpty) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripEmpty) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2388,8 +2524,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripEmpty) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripWithTwoSummaryTypes) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripWithTwoSummaryTypes) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2558,8 +2694,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripWithTwoSummaryTypes) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripLinkUnit) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripLinkUnit) { + readWriteCompare(R"({ "tu_namespace": { "kind": "LinkUnit", "name": "libtest.so" @@ -2570,8 +2706,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripLinkUnit) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripWithEmptyDataEntry) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripWithEmptyDataEntry) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2587,8 +2723,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripWithEmptyDataEntry) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithNoneLinkage) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripLinkageTableWithNoneLinkage) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2618,8 +2754,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithNoneLinkage) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithInternalLinkage) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripLinkageTableWithInternalLinkage) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2649,8 +2785,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithInternalLinkage) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithExternalLinkage) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripLinkageTableWithExternalLinkage) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" @@ -2680,8 +2816,8 @@ TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithExternalLinkage) { })"); } -TEST_F(JSONFormatTUSummaryTest, RoundTripLinkageTableWithMultipleEntries) { - readWriteCompareTUSummary(R"({ +TEST_P(TUSummaryTest, RoundTripLinkageTableWithMultipleEntries) { + readWriteCompare(R"({ "tu_namespace": { "kind": "CompilationUnit", "name": "test.cpp" From cf28f23f10133f0419768ce8284fe05fa079f93c Mon Sep 17 00:00:00 2001 From: Akash Dutta <137309513+akadutta@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:00:58 -0600 Subject: [PATCH 31/58] [SLP] Reject duplicate shift amounts in matchesShlZExt reorder path (#183627) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the reordered RHS path of matchesShlZExt, the code never checked that each shift amount (0, Stride, 2×Stride, …) appears at most once. When the same shift appeared in multiple lanes, it still filled Order, producing a non-permutation (e.g. Order = [0,0,0,1]). That led to bad shuffle masks and miscompilation (e.g. shuffles with poison). The patch adds an explicit duplicate check: before setting Order[Idx] = Pos, it ensures Pos has not been seen before, using a SmallBitVector SeenPositions(VF). If a position is seen twice, the function returns false and the optimization is not applied. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 5 +++++ .../AMDGPU/zext-duplicate-shift.ll | 22 ++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 3a10d2b2a7158..db4845113d58b 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13420,6 +13420,8 @@ bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order, } else { const unsigned VF = RhsTE->getVectorFactor(); Order.assign(VF, VF); + // Track which logical positions we've seen; reject duplicate shift amounts. + SmallBitVector SeenPositions(VF); // Check if need to reorder Rhs to make it in form (0, Stride, 2 * Stride, // ..., Sz-Stride). if (VF * Stride != Sz) @@ -13437,6 +13439,9 @@ bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order, // TODO: Support Pos >= VF, in this case need to shift the final value. if (Order[Idx] != VF || Pos >= VF) return false; + if (SeenPositions.test(Pos)) + return false; + SeenPositions.set(Pos); Order[Idx] = Pos; } // One of the indices not set - exit. diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/zext-duplicate-shift.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/zext-duplicate-shift.ll index abe95d30a528d..6ae9c70b9ecc0 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/zext-duplicate-shift.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/zext-duplicate-shift.ll @@ -10,17 +10,23 @@ define void @duplicate_shift_i128_store(ptr %base, i32 %spec_select, i32 %spec_s ; CHECK-NEXT: [[ZEXT37:%.*]] = zext i32 [[SPEC_SELECT37]] to i128 ; CHECK-NEXT: [[SHL37:%.*]] = shl nuw nsw i128 [[ZEXT37]], 32 ; CHECK-NEXT: [[MASKED37:%.*]] = and i128 [[SHL37]], 18446742974197923840 -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[SPEC_SELECT]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[SPEC_SELECT37]], i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i32> [[TMP2]], +; CHECK-NEXT: [[AND37_255:%.*]] = and i32 [[SPEC_SELECT37]], 255 +; CHECK-NEXT: [[ZEXT37_255:%.*]] = zext nneg i32 [[AND37_255]] to i128 +; CHECK-NEXT: [[SHL37_255:%.*]] = shl nuw nsw i128 [[ZEXT37_255]], 32 +; CHECK-NEXT: [[P_MASK_7:%.*]] = or disjoint i128 [[P_INSERT_11]], [[MASKED37]] +; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i128 [[P_MASK_7]], [[SHL37_255]] ; CHECK-NEXT: [[PREFIX_HIGH:%.*]] = and i32 [[SPEC_SELECT]], -16777216 ; CHECK-NEXT: [[ZEXT_HIGH:%.*]] = zext i32 [[PREFIX_HIGH]] to i128 -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i32> [[TMP4]] to i128 ; CHECK-NEXT: [[P_MASK_0:%.*]] = or disjoint i128 [[TMP5]], [[ZEXT_HIGH]] -; CHECK-NEXT: [[ZEXT_255:%.*]] = or disjoint i128 [[MASKED37]], [[P_INSERT_11]] -; CHECK-NEXT: [[P_INSERT_0:%.*]] = or disjoint i128 [[P_MASK_0]], [[ZEXT_255]] +; CHECK-NEXT: [[AND_16711680:%.*]] = and i32 [[SPEC_SELECT]], 16711680 +; CHECK-NEXT: [[ZEXT_16711680:%.*]] = zext nneg i32 [[AND_16711680]] to i128 +; CHECK-NEXT: [[P_MASK_4:%.*]] = or disjoint i128 [[P_MASK_0]], [[ZEXT_16711680]] +; CHECK-NEXT: [[AND_255:%.*]] = and i32 [[SPEC_SELECT]], 255 +; CHECK-NEXT: [[ZEXT_255:%.*]] = zext nneg i32 [[AND_255]] to i128 +; CHECK-NEXT: [[AND_65280:%.*]] = and i32 [[SPEC_SELECT]], 65280 +; CHECK-NEXT: [[ZEXT_65280:%.*]] = zext nneg i32 [[AND_65280]] to i128 +; CHECK-NEXT: [[P_MASK_1:%.*]] = or disjoint i128 [[P_MASK_4]], [[ZEXT_65280]] +; CHECK-NEXT: [[P_INSERT_0:%.*]] = or disjoint i128 [[P_MASK_1]], [[ZEXT_255]] ; CHECK-NEXT: store i128 [[P_INSERT_0]], ptr [[ARRAYIDX]], align 16 ; CHECK-NEXT: ret void ; From 25d709e72c976f8f7420a342e7916b46b6c23e28 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Fri, 27 Feb 2026 14:02:00 -0500 Subject: [PATCH 32/58] [SystemZ] Emit external aliases for indirect function descriptors in the ADA section (#183443) This is the last of the three patches aimed to support indirect symbol handling for the SystemZ backend. An external alias is emitted for indirect function descriptors within the ADA section, rather than a temporary alias, while also setting all of the appropriate symbol attributes that are needed for the HLASM streamer to emit the correct XATTR and ALIAS instructions for the indirect symbols. Moreover, this patch updates the `CodeGen/SystemZ/zos-ada-relocations.ll` test as the ADA section is currently the only user of indirect symbols on z/OS. Depends on https://github.com/llvm/llvm-project/pull/183442. --- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 11 +++++++---- llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll | 6 +++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 58c8b30f96b4c..cb451a1ca4f55 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -1275,12 +1275,15 @@ void SystemZAsmPrinter::emitADASection() { EmittedBytes += PointerSize; break; case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: { - MCSymbol *Alias = OutContext.createTempSymbol( + MCSymbol *Alias = OutContext.getOrCreateSymbol( Twine(Sym->getName()).concat("@indirect")); - OutStreamer->emitAssignment(Alias, - MCSymbolRefExpr::create(Sym, OutContext)); OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol); - + OutStreamer->emitSymbolAttribute(Alias, MCSA_ELF_TypeFunction); + OutStreamer->emitSymbolAttribute(Alias, MCSA_Global); + OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern); + MCSymbolGOFF *GOFFSym = + static_cast(const_cast(Sym)); + getTargetStreamer()->emitExternalName(Alias, GOFFSym->getExternalName()); EMIT_COMMENT("pointer to function descriptor"); OutStreamer->emitValue( MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext), diff --git a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll index f3bdf64683bb6..a79e3b67ac3d1 100644 --- a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll +++ b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll @@ -60,7 +60,7 @@ declare signext i32 @callout(i32 signext) ; CHECK: in#S) ; CHECK: stdin#S XATTR LINKAGE(XPLINK),REFERENCE(DATA),SCOPE(SECTION) ; CHECK: * Offset 0 pointer to function descriptor DoFunc -; CHECK: DC VD(L#DoFunc@indirect0) +; CHECK: DC VD(DoFunc@indirect) ; CHECK: * Offset 8 function descriptor of Caller ; CHECK: DC RD(Caller) ; CHECK: DC VD(Caller) @@ -71,3 +71,7 @@ declare signext i32 @callout(i32 signext) ; CHECK: * Offset 40 function descriptor of callout ; CHECK: DC RD(callout) ; CHECK: DC VD(callout) +; CHECK: EXTRN DoFunc@indirect +; CHECK: DoFunc@indirect XATTR LINKAGE(XPLINK),REFERENCE(CODE,INDIRECT),SCOPE(EX +; CHECK: PORT) +; CHECK: DoFunc@indirect ALIAS C'DoFunc' From ee6f5f386f95753d869045acbe54a6b3ec38dde9 Mon Sep 17 00:00:00 2001 From: Manuel Carrasco Date: Fri, 27 Feb 2026 19:13:57 +0000 Subject: [PATCH 33/58] [InstCombine] Replace alloca with undef size with poison instead of null (#182919) InstCombine previously replaced an alloca instruction with a null pointer when the array size operand was undef. While this replacement may be legal, it still caused invalid IR in cases where the original alloca was used by `@llvm.lifetime` intrinsics. The spec requires that the pointer operand of `@llvm.lifetime.*` must be either: - a pointer to an alloca instruction, or - a poison value. Replacing the pointer with null violated this requirement and triggered verifier errors. These new changes update InstCombine so that in this scenario the alloca is replaced with poison instead of null. --- .../InstCombineLoadStoreAlloca.cpp | 2 +- .../InstCombine/alloca-poison-size.ll | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/InstCombine/alloca-poison-size.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index d27ad636af9e2..277f81245ade2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -210,7 +210,7 @@ static Instruction *simplifyAllocaArraySize(InstCombinerImpl &IC, } if (isa(AI.getArraySize())) - return IC.replaceInstUsesWith(AI, Constant::getNullValue(AI.getType())); + return IC.replaceInstUsesWith(AI, PoisonValue::get(AI.getType())); // Ensure that the alloca array size argument has type equal to the offset // size of the alloca() pointer, which, in the tyical case, is intptr_t, diff --git a/llvm/test/Transforms/InstCombine/alloca-poison-size.ll b/llvm/test/Transforms/InstCombine/alloca-poison-size.ll new file mode 100644 index 0000000000000..d96181b845b50 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/alloca-poison-size.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +; InstCombineLoadStoreAlloca replaced alloca uses with null when the +; alloca size was poison. This causes invalid IR: +; +; call void @llvm.lifetime.start(ptr %i_) +; becomes: +; call void @llvm.lifetime.start(ptr null) +; +; According to the lifetime intrinsic spec, the argument must be either: +; - A pointer to an alloca instruction, or +; - A poison value. +; +; Since null is neither an alloca pointer nor poison, this transformation +; produced invalid IR. + +define i32 @foo() { +; CHECK-LABEL: define i32 @foo() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: store i32 0, ptr poison, align 4 +; CHECK-NEXT: ret i32 0 +; +entry: + %i_ = alloca i32, i32 poison, align 4 + call void @llvm.lifetime.start(ptr %i_) + store i32 0, ptr %i_, align 4 + ret i32 0 +} From 8ce2b9cbc2bcde50189e74650cf994e8f549f58d Mon Sep 17 00:00:00 2001 From: Tommy Chiang Date: Sat, 28 Feb 2026 03:18:11 +0800 Subject: [PATCH 34/58] [Clang][ItaniumMangle] Fix recursive mangling for lambda init-captures (#182667) [Clang][ItaniumMangle] Fix recursive mangling for lambda init-captures Mangle computation for lambda signatures can recurse when a call operator type references an init-capture (for example via decltype(init-capture)). In these cases, mangling can re-enter the init-capture declaration and cycle back through operator() mangling. Make lambda context publication explicit and independent from numbering state, then use that context uniformly during mangling: * Publish lambda `ContextDecl` in `Sema::handleLambdaNumbering()` before numbering, so dependent type mangling can resolve the lambda context without recursing through the call operator. * Introduce `CXXRecordDecl::setLambdaContextDecl()` and remove `ContextDecl` from `CXXRecordDecl::LambdaNumbering`. * Update `ASTImporter` to import/set lambda context separately from numbering. * In Itanium mangling, derive init-capture handling from context computation: - map local-lambda init-captures to the enclosing local context in `getEffectiveDeclContext()` - support init-capture variables in `getClosurePrefix()` - keep `mangleLocalName()` generic and rely on the computed context Add mangling regression coverage in mangle-lambdas.cpp, including: * local init-captures used through decltype * non-local variable-template init-captures in decltype * non-local static inline member init-captures in decltype * Fixes https://github.com/llvm/llvm-project/issues/63271 * Fixes https://github.com/llvm/llvm-project/issues/86240 * Fixes https://github.com/llvm/llvm-project/issues/139089 --- clang/include/clang/AST/DeclCXX.h | 13 ++--- clang/lib/AST/ASTImporter.cpp | 10 ++-- clang/lib/AST/DeclCXX.cpp | 6 ++- clang/lib/AST/ItaniumMangle.cpp | 38 +++++++++++--- clang/lib/Sema/SemaLambda.cpp | 24 ++++++--- clang/test/CodeGenCXX/mangle-lambdas.cpp | 66 ++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 15dda098bad47..48fd12efdcafe 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1791,6 +1791,9 @@ class CXXRecordDecl : public RecordDecl { /// the declaration context suffices. Decl *getLambdaContextDecl() const; + /// Set the context declaration for a lambda class. + void setLambdaContextDecl(Decl *ContextDecl); + /// Retrieve the index of this lambda within the context declaration returned /// by getLambdaContextDecl(). unsigned getLambdaIndexInContext() const { @@ -1800,21 +1803,19 @@ class CXXRecordDecl : public RecordDecl { /// Information about how a lambda is numbered within its context. struct LambdaNumbering { - Decl *ContextDecl = nullptr; unsigned IndexInContext = 0; unsigned ManglingNumber = 0; unsigned DeviceManglingNumber = 0; bool HasKnownInternalLinkage = false; }; - /// Set the mangling numbers and context declaration for a lambda class. + /// Set the mangling numbers for a lambda class. void setLambdaNumbering(LambdaNumbering Numbering); - // Get the mangling numbers and context declaration for a lambda class. + // Get the mangling numbers for a lambda class. LambdaNumbering getLambdaNumbering() const { - return {getLambdaContextDecl(), getLambdaIndexInContext(), - getLambdaManglingNumber(), getDeviceLambdaManglingNumber(), - hasKnownLambdaInternalLinkage()}; + return {getLambdaIndexInContext(), getLambdaManglingNumber(), + getDeviceLambdaManglingNumber(), hasKnownLambdaInternalLinkage()}; } /// Retrieve the device side mangling number. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 8d8cc5426146d..c41d0c744e664 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3444,12 +3444,14 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; - CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering(); - ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl); + Decl *ContextDecl = DCXX->getLambdaContextDecl(); + ExpectedDecl CDeclOrErr = import(ContextDecl); if (!CDeclOrErr) return CDeclOrErr.takeError(); - Numbering.ContextDecl = *CDeclOrErr; - D2CXX->setLambdaNumbering(Numbering); + if (ContextDecl != nullptr) { + D2CXX->setLambdaContextDecl(*CDeclOrErr); + } + D2CXX->setLambdaNumbering(DCXX->getLambdaNumbering()); } else { if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, Loc, diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 37bc61ca35c4b..083c53e28cb91 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1837,6 +1837,11 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } +void CXXRecordDecl::setLambdaContextDecl(Decl *ContextDecl) { + assert(isLambda() && "Not a lambda closure type!"); + getLambdaData().ContextDecl = ContextDecl; +} + void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { assert(isLambda() && "Not a lambda closure type!"); getLambdaData().ManglingNumber = Numbering.ManglingNumber; @@ -1844,7 +1849,6 @@ void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { getASTContext().DeviceLambdaManglingNumbers[this] = Numbering.DeviceManglingNumber; getLambdaData().IndexInContext = Numbering.IndexInContext; - getLambdaData().ContextDecl = Numbering.ContextDecl; getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7c34377fc6e1a..04201fc11c4ac 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -634,6 +634,19 @@ NamespaceDecl *ItaniumMangleContextImpl::getStdNamespace() { return StdNamespace; } +/// Retrieve the lambda associated with an init-capture variable. +static const CXXRecordDecl *getLambdaForInitCapture(const VarDecl *VD) { + if (!VD || !VD->isInitCapture()) + return nullptr; + + const auto *Method = cast(VD->getDeclContext()); + const auto *Lambda = dyn_cast(Method->getParent()); + if (!Lambda || !Lambda->isLambda()) + return nullptr; + + return Lambda; +} + /// Retrieve the declaration context that should be used when mangling the given /// declaration. const DeclContext * @@ -675,9 +688,18 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { return getEffectiveDeclContext(cast(DC)); } - if (const auto *VD = dyn_cast(D)) + if (const auto *VD = dyn_cast(D)) { + if (const CXXRecordDecl *Lambda = getLambdaForInitCapture(VD)) { + const DeclContext *ParentDC = getEffectiveParentContext(Lambda); + // Init-captures in local lambdas are mangled relative to the enclosing + // local context rather than operator() to avoid recursive local-name + // encoding through the call operator type. + if (isLocalContainerContext(ParentDC)) + return ParentDC; + } if (VD->isExternC()) return getASTContext().getTranslationUnitDecl(); + } if (const auto *FD = getASTContext().getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver19 @@ -1874,12 +1896,13 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, { AbiTagState LocalAbiTags(AbiTags); - if (const ObjCMethodDecl *MD = dyn_cast(DC)) + if (const ObjCMethodDecl *MD = dyn_cast(DC)) { mangleObjCMethodName(MD); - else if (const BlockDecl *BD = dyn_cast(DC)) + } else if (const BlockDecl *BD = dyn_cast(DC)) { mangleBlockForPrefix(BD); - else + } else { mangleFunctionEncoding(getParentOfLocalEntity(DC)); + } // Implicit ABI tags (from namespace) are not available in the following // entity; reset to actually emitted tags, which are available. @@ -2278,6 +2301,9 @@ const NamedDecl *CXXNameMangler::getClosurePrefix(const Decl *ND) { const NamedDecl *Context = nullptr; if (auto *Block = dyn_cast(ND)) { Context = dyn_cast_or_null(Block->getBlockManglingContextDecl()); + } else if (auto *VD = dyn_cast(ND)) { + if (const CXXRecordDecl *Lambda = getLambdaForInitCapture(VD)) + Context = dyn_cast_or_null(Lambda->getLambdaContextDecl()); } else if (auto *RD = dyn_cast(ND)) { if (RD->isLambda()) Context = dyn_cast_or_null(RD->getLambdaContextDecl()); @@ -2285,8 +2311,8 @@ const NamedDecl *CXXNameMangler::getClosurePrefix(const Decl *ND) { if (!Context) return nullptr; - // Only lambdas within the initializer of a non-local variable or non-static - // data member get a . + // Only entities associated with lambdas within the initializer of a + // non-local variable or non-static data member get a . if ((isa(Context) && cast(Context)->hasGlobalStorage()) || isa(Context)) return Context; diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index be7f73dbc267f..8572e3a742a6c 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -491,11 +491,6 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda( void Sema::handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, std::optional NumberingOverride) { - if (NumberingOverride) { - Class->setLambdaNumbering(*NumberingOverride); - return; - } - ContextRAII ManglingContext(*this, Class->getDeclContext()); auto getMangleNumberingContext = @@ -512,10 +507,23 @@ void Sema::handleLambdaNumbering( return &Context.getManglingNumberContext(DC); }; - CXXRecordDecl::LambdaNumbering Numbering; MangleNumberingContext *MCtx; - std::tie(MCtx, Numbering.ContextDecl) = + Decl *ContextDecl; + std::tie(MCtx, ContextDecl) = getCurrentMangleNumberContext(Class->getDeclContext()); + // getManglingNumber(Method) below may trigger mangling of dependent types + // that reference init-captures. Publish the lambda context declaration early + // so such mangling can resolve the surrounding context without recursing + // through the lambda call operator. This avoids publishing provisional + // numbering state before final numbering is assigned below. + if (ContextDecl) + Class->setLambdaContextDecl(ContextDecl); + if (NumberingOverride) { + Class->setLambdaNumbering(*NumberingOverride); + return; + } + + CXXRecordDecl::LambdaNumbering Numbering; if (!MCtx && (getLangOpts().CUDA || getLangOpts().SYCLIsDevice || getLangOpts().SYCLIsHost)) { // Force lambda numbering in CUDA/HIP as we need to name lambdas following @@ -525,7 +533,7 @@ void Sema::handleLambdaNumbering( // Also force for SYCL, since we need this for the // __builtin_sycl_unique_stable_name implementation, which depends on lambda // mangling. - MCtx = getMangleNumberingContext(Class, Numbering.ContextDecl); + MCtx = getMangleNumberingContext(Class, ContextDecl); assert(MCtx && "Retrieving mangle numbering context failed!"); Numbering.HasKnownInternalLinkage = true; } diff --git a/clang/test/CodeGenCXX/mangle-lambdas.cpp b/clang/test/CodeGenCXX/mangle-lambdas.cpp index 5a7de97c91858..d9ac0d39956e9 100644 --- a/clang/test/CodeGenCXX/mangle-lambdas.cpp +++ b/clang/test/CodeGenCXX/mangle-lambdas.cpp @@ -301,6 +301,70 @@ void test_StaticInlineMember() { StaticInlineMember::x(); } +template +auto pr63271foo(L l_) { + return [l = l_](decltype(l)) -> void {}; +} + +// CHECK-LABEL: define{{.*}} @_Z10pr63271usev +// CHECK: call void @_ZZ10pr63271fooIiEDaT_ENKUliE_clEi +void pr63271use() { + pr63271foo(0)(0); +} + +template +struct pr139089_vlambda { + pr139089_vlambda() { + [&m = m_args](decltype(m) args) { (void)args; }(m_args); + } + int m_args = 0; +}; + +// CHECK-LABEL: define{{.*}} @_Z11pr139089usev +// CHECK: call void @_ZN16pr139089_vlambdaIiEC1Ev +void pr139089use() { + (void)pr139089_vlambda{}; +} + + +template struct pr86240_context { + using Ptr = pr86240_context *; +}; + +template +void pr86240_schedule_coro(Callable &&coro_function) { + [coro_function{coro_function}]( + typename pr86240_context::Ptr ctx) -> int { + return ctx != nullptr; + }(nullptr); +} + +// CHECK-LABEL: define{{.*}} @_Z10pr86240usev +// CHECK: call noundef i32 @"_ZZ21pr86240_schedule_coroIZ10pr86240usevE3$_0EvOT_ENKUlP15pr86240_contextIiEE_clES5_" +void pr86240use() { + pr86240_schedule_coro([] { return 0; }); +} + +template +auto nonLocalVarTemplate = [x = T{}](decltype(x) y) { return y; }; + +// CHECK-LABEL: define{{.*}} @_Z22nonLocalVarTemplateUsev +// CHECK: call noundef i32 @_ZNK19nonLocalVarTemplateIiEMUliE_clEi +int nonLocalVarTemplateUse() { + return nonLocalVarTemplate(2); +} + +template +struct nonLocalStaticInlineMember { + static inline auto l = [x = T{}](decltype(x) y) { return y; }; +}; + +// CHECK-LABEL: define{{.*}} @_Z29nonLocalStaticInlineMemberUsev +// CHECK: call noundef i32 @_ZNK26nonLocalStaticInlineMemberIiE1lMUliE_clEi +int nonLocalStaticInlineMemberUse() { + return nonLocalStaticInlineMember::l(2); +} + // Check linkage of the various lambdas. // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZ11inline_funciENKUlvE_clEv // CHECK: ret i32 1 @@ -331,6 +395,8 @@ void test_StaticInlineMember() { // CHECK-LABEL: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_ +// CHECK-LABEL: define linkonce_odr void @_ZZN16pr139089_vlambdaIiEC1EvENKUlRiE_clES1_ + namespace PR12808 { template struct B { From df5bee6afc79eb393c6dcbaad1b2ab3665f3a853 Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Fri, 27 Feb 2026 11:20:43 -0800 Subject: [PATCH 35/58] [CIR] Implement TryOp flattening (#183591) This updates the FlattenCFG pass to add flattening for cir::TryOp in cases where the TryOp contains catch or unwind handlers. Substantial amounts of this PR were created using agentic AI tools, but I have carefully reviewed the code, comments, and tests and made changes as needed. I've left intermediate commits in the initial PR if you'd like to see the progression. --- .../lib/CIR/Dialect/Transforms/FlattenCFG.cpp | 453 +++++++---- .../Transforms/flatten-cleanup-scope-nyi.cir | 90 --- clang/test/CIR/Transforms/flatten-try-op.cir | 737 ++++++++++++++++++ 3 files changed, 1027 insertions(+), 253 deletions(-) create mode 100644 clang/test/CIR/Transforms/flatten-try-op.cir diff --git a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp index 4c13594258465..5ca98bc9a9c7a 100644 --- a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp +++ b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp @@ -606,6 +606,79 @@ static cir::AllocaOp getOrCreateCleanupDestSlot(cir::FuncOp funcOp, return allocaOp; } +/// Shared EH flattening utilities used by both CIRCleanupScopeOpFlattening +/// and CIRTryOpFlattening. + +// Collect all function calls in a region that may throw exceptions and need +// to be replaced with try_call operations. Skips calls marked nothrow. +// Nested cleanup scopes and try ops are always flattened before their +// enclosing parents, so there are no nested regions to skip here. +static void +collectThrowingCalls(mlir::Region ®ion, + llvm::SmallVectorImpl &callsToRewrite) { + region.walk([&](cir::CallOp callOp) { + if (!callOp.getNothrow()) + callsToRewrite.push_back(callOp); + }); +} + +// Collect all cir.resume operations in a region that come from +// already-flattened try or cleanup scope operations. These resume ops need +// to be chained through this scope's EH handler instead of unwinding +// directly to the caller. Nested cleanup scopes and try ops are always +// flattened before their enclosing parents, so there are no nested regions +// to skip here. +static void collectResumeOps(mlir::Region ®ion, + llvm::SmallVectorImpl &resumeOps) { + region.walk([&](cir::ResumeOp resumeOp) { resumeOps.push_back(resumeOp); }); +} + +// Replace a cir.call with a cir.try_call that unwinds to the `unwindDest` +// block if an exception is thrown. +static void replaceCallWithTryCall(cir::CallOp callOp, mlir::Block *unwindDest, + mlir::Location loc, + mlir::PatternRewriter &rewriter) { + mlir::Block *callBlock = callOp->getBlock(); + + assert(!callOp.getNothrow() && "call is not expected to throw"); + + // Split the block after the call - remaining ops become the normal + // destination. + mlir::Block *normalDest = + rewriter.splitBlock(callBlock, std::next(callOp->getIterator())); + + // Build the try_call to replace the original call. + rewriter.setInsertionPoint(callOp); + mlir::Type resType = callOp->getNumResults() > 0 + ? callOp->getResult(0).getType() + : mlir::Type(); + auto tryCallOp = + cir::TryCallOp::create(rewriter, loc, callOp.getCalleeAttr(), resType, + normalDest, unwindDest, callOp.getArgOperands()); + + // Replace uses of the call result with the try_call result. + if (callOp->getNumResults() > 0) + callOp->getResult(0).replaceAllUsesWith(tryCallOp.getResult()); + + rewriter.eraseOp(callOp); +} + +// Create a shared unwind destination block. The block contains a +// cir.eh.initiate operation (optionally with the cleanup attribute) and a +// branch to the given destination block, passing the eh_token. +static mlir::Block *buildUnwindBlock(mlir::Block *dest, bool hasCleanup, + mlir::Location loc, + mlir::Block *insertBefore, + mlir::PatternRewriter &rewriter) { + mlir::Block *unwindBlock = rewriter.createBlock(insertBefore); + rewriter.setInsertionPointToEnd(unwindBlock); + auto ehInitiate = + cir::EhInitiateOp::create(rewriter, loc, /*cleanup=*/hasCleanup); + cir::BrOp::create(rewriter, loc, mlir::ValueRange{ehInitiate.getEhToken()}, + dest); + return unwindBlock; +} + class CIRCleanupScopeOpFlattening : public mlir::OpRewritePattern { public: @@ -883,45 +956,6 @@ class CIRCleanupScopeOpFlattening }); } - // Collect all cir.resume operations in the body region that come from - // already-flattened try or cleanup scope operations that were nested within - // this cleanup scope. These resume ops need to be chained through this - // cleanup's EH handler instead of unwinding directly to the caller. - void collectResumeOps(mlir::Region &bodyRegion, - llvm::SmallVectorImpl &resumeOps) const { - bodyRegion.walk([&](mlir::Operation *op) { - // Skip resume ops inside nested TryOps - those are handled by TryOp - // flattening. - if (isa(op)) - return mlir::WalkResult::skip(); - - if (auto resumeOp = dyn_cast(op)) - resumeOps.push_back(resumeOp); - return mlir::WalkResult::advance(); - }); - } - - // Collect all function calls in the cleanup scope body that may throw - // exceptions and need to be replaced with try_call operations. Skips calls - // that are marked nothrow and calls inside nested TryOps (the latter will be - // handled by the TryOp's own flattening). - void collectThrowingCalls( - mlir::Region &bodyRegion, - llvm::SmallVectorImpl &callsToRewrite) const { - bodyRegion.walk([&](mlir::Operation *op) { - // Skip calls inside nested TryOps - those are handled by TryOp - // flattening. - if (isa(op)) - return mlir::WalkResult::skip(); - - if (auto callOp = dyn_cast(op)) { - if (!callOp.getNothrow()) - callsToRewrite.push_back(callOp); - } - return mlir::WalkResult::advance(); - }); - } - #ifndef NDEBUG // Check that no block other than the last one in a region exits the region. static bool regionExitsOnlyFromLastBlock(mlir::Region ®ion) { @@ -1051,51 +1085,6 @@ class CIRCleanupScopeOpFlattening return clonedEntry; } - // Create a shared unwind destination block for all calls within the same - // cleanup scope. The unwind block contains a cir.eh.initiate operation - // (with the cleanup attribute) and a branch to the EH cleanup block. - mlir::Block *buildUnwindBlock(mlir::Block *ehCleanupBlock, mlir::Location loc, - mlir::Block *insertBefore, - mlir::PatternRewriter &rewriter) const { - mlir::Block *unwindBlock = rewriter.createBlock(insertBefore); - rewriter.setInsertionPointToEnd(unwindBlock); - auto ehInitiate = - cir::EhInitiateOp::create(rewriter, loc, /*cleanup=*/true); - cir::BrOp::create(rewriter, loc, mlir::ValueRange{ehInitiate.getEhToken()}, - ehCleanupBlock); - return unwindBlock; - } - - // Replace a cir.call with a cir.try_call that unwinds to the `unwindDest` - // block if an exception is thrown. - void replaceCallWithTryCall(cir::CallOp callOp, mlir::Block *unwindDest, - mlir::Location loc, - mlir::PatternRewriter &rewriter) const { - mlir::Block *callBlock = callOp->getBlock(); - - assert(!callOp.getNothrow() && "call is not expected to throw"); - - // Split the block after the call - remaining ops become the normal - // destination. - mlir::Block *normalDest = - rewriter.splitBlock(callBlock, std::next(callOp->getIterator())); - - // Build the try_call to replace the original call. - rewriter.setInsertionPoint(callOp); - mlir::Type resType = callOp->getNumResults() > 0 - ? callOp->getResult(0).getType() - : mlir::Type(); - auto tryCallOp = - cir::TryCallOp::create(rewriter, loc, callOp.getCalleeAttr(), resType, - normalDest, unwindDest, callOp.getArgOperands()); - - // Replace uses of the call result with the try_call result. - if (callOp->getNumResults() > 0) - callOp->getResult(0).replaceAllUsesWith(tryCallOp.getResult()); - - rewriter.eraseOp(callOp); - } - // Flatten a cleanup scope. The body region's exits branch to the cleanup // block, and the cleanup block branches to destination blocks whose contents // depend on the type of operation that exited the body region. Yield becomes @@ -1180,8 +1169,8 @@ class CIRCleanupScopeOpFlattening // need a shared unwind destination. Resume ops from inner cleanups // branch directly to the EH cleanup entry. if (!callsToRewrite.empty()) - unwindBlock = - buildUnwindBlock(ehCleanupEntry, loc, ehCleanupEntry, rewriter); + unwindBlock = buildUnwindBlock(ehCleanupEntry, /*hasCleanup=*/true, loc, + ehCleanupEntry, rewriter); } // All normal flow blocks are inserted before this point — either before @@ -1385,106 +1374,244 @@ class CIRTryOpFlattening : public mlir::OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; - mlir::Block *buildTryBody(cir::TryOp tryOp, - mlir::PatternRewriter &rewriter) const { - // Split the current block before the TryOp to create the inlining - // point. - mlir::Block *beforeTryScopeBlock = rewriter.getInsertionBlock(); - mlir::Block *afterTry = - rewriter.splitBlock(beforeTryScopeBlock, rewriter.getInsertionPoint()); + // Build the catch dispatch block with a cir.eh.dispatch operation. + // The dispatch block receives an !cir.eh_token argument and dispatches + // to the appropriate catch handler blocks based on exception types. + mlir::Block *buildCatchDispatchBlock( + cir::TryOp tryOp, mlir::ArrayAttr handlerTypes, + llvm::SmallVectorImpl &catchHandlerBlocks, + mlir::Location loc, mlir::Block *insertBefore, + mlir::PatternRewriter &rewriter) const { + mlir::Block *dispatchBlock = rewriter.createBlock(insertBefore); + auto ehTokenType = cir::EhTokenType::get(rewriter.getContext()); + mlir::Value ehToken = dispatchBlock->addArgument(ehTokenType, loc); + + rewriter.setInsertionPointToEnd(dispatchBlock); + + // Build the catch types and destinations for the dispatch. + llvm::SmallVector catchTypeAttrs; + llvm::SmallVector catchDests; + mlir::Block *defaultDest = nullptr; + bool defaultIsCatchAll = false; + + for (auto [typeAttr, handlerBlock] : + llvm::zip(handlerTypes, catchHandlerBlocks)) { + if (mlir::isa(typeAttr)) { + assert(!defaultDest && "multiple catch_all or unwind handlers"); + defaultDest = handlerBlock; + defaultIsCatchAll = true; + } else if (mlir::isa(typeAttr)) { + assert(!defaultDest && "multiple catch_all or unwind handlers"); + defaultDest = handlerBlock; + defaultIsCatchAll = false; + } else { + // This is a typed catch handler (GlobalViewAttr with type info). + catchTypeAttrs.push_back(typeAttr); + catchDests.push_back(handlerBlock); + } + } - // Inline body region. - mlir::Block *beforeBody = &tryOp.getTryRegion().front(); - rewriter.inlineRegionBefore(tryOp.getTryRegion(), afterTry); + assert(defaultDest && "dispatch must have a catch_all or unwind handler"); - // Branch into the body of the region. - rewriter.setInsertionPointToEnd(beforeTryScopeBlock); - cir::BrOp::create(rewriter, tryOp.getLoc(), mlir::ValueRange(), beforeBody); - return afterTry; - } + mlir::ArrayAttr catchTypesArrayAttr; + if (!catchTypeAttrs.empty()) + catchTypesArrayAttr = rewriter.getArrayAttr(catchTypeAttrs); - void buildHandlers(cir::TryOp tryOp, mlir::PatternRewriter &rewriter, - mlir::Block *afterBody, mlir::Block *afterTry, - SmallVectorImpl &callsToRewrite, - SmallVectorImpl &landingPads) const { - // Replace the tryOp return with a branch that jumps out of the body. - rewriter.setInsertionPointToEnd(afterBody); + cir::EhDispatchOp::create(rewriter, loc, ehToken, catchTypesArrayAttr, + defaultIsCatchAll, defaultDest, catchDests); - mlir::Block *beforeCatch = rewriter.getInsertionBlock(); - rewriter.setInsertionPointToEnd(beforeCatch); + return dispatchBlock; + } - // Check if the terminator is a YieldOp because there could be another - // terminator, e.g. unreachable - if (auto tryBodyYield = dyn_cast(afterBody->getTerminator())) - rewriter.replaceOpWithNewOp(tryBodyYield, afterTry); + // Flatten a single catch handler region. Each handler region has an + // !cir.eh_token argument and starts with cir.begin_catch, followed by + // a cir.cleanup.scope containing the handler body (with cir.end_catch in + // its cleanup region), and ending with cir.yield. + // + // After flattening, the handler region becomes a block that receives the + // eh_token, calls begin_catch, runs the handler body inline, calls + // end_catch, and branches to the continue block. + // + // The cleanup scope inside the catch handler is expected to have been + // flattened before we get here, so what we see in the handler region is + // already flat code with begin_catch at the top and end_catch in any place + // that we would exit the catch handler. We just need to inline the region + // and fix up terminators. + mlir::Block *flattenCatchHandler(mlir::Region &handlerRegion, + mlir::Block *continueBlock, + mlir::Location loc, + mlir::Block *insertBefore, + mlir::PatternRewriter &rewriter) const { + // The handler region entry block has the !cir.eh_token argument. + mlir::Block *handlerEntry = &handlerRegion.front(); + + // Inline the handler region before insertBefore. + rewriter.inlineRegionBefore(handlerRegion, insertBefore); + + // Replace yield terminators in the handler with branches to continue. + for (mlir::Block &block : llvm::make_range(handlerEntry->getIterator(), + insertBefore->getIterator())) { + if (auto yieldOp = dyn_cast(block.getTerminator())) { + // Verify that end_catch is the last non-branch operation before + // this yield. After cleanup scope flattening, end_catch may be in + // a predecessor block rather than immediately before the yield. + // Walk back through the single-predecessor chain, verifying that + // each intermediate block contains only a branch terminator, until + // we find end_catch as the last non-terminator in some block. + assert([&]() { + // Check if end_catch immediately precedes the yield. + if (mlir::Operation *prev = yieldOp->getPrevNode()) + return isa(prev); + // The yield is alone in its block. Walk backward through + // single-predecessor blocks that contain only a branch. + mlir::Block *b = block.getSinglePredecessor(); + while (b) { + mlir::Operation *term = b->getTerminator(); + if (mlir::Operation *prev = term->getPrevNode()) + return isa(prev); + if (!isa(term)) + return false; + b = b->getSinglePredecessor(); + } + return false; + }() && "expected end_catch as last operation before yield " + "in catch handler, with only branches in between"); + rewriter.setInsertionPoint(yieldOp); + rewriter.replaceOpWithNewOp(yieldOp, continueBlock); + } + } - mlir::ArrayAttr handlers = tryOp.getHandlerTypesAttr(); - if (!handlers || handlers.empty()) - return; + return handlerEntry; + } - llvm_unreachable("TryOpFlattening buildHandlers with CallsOp is NYI"); + // Flatten an unwind handler region. The unwind region just contains a + // cir.resume that continues unwinding. We inline it and leave the resume + // in place. If this try op is nested inside an EH cleanup or another try op, + // the enclosing op will rewrite the resume as a branch to its cleanup or + // dispatch block when it is flattened. Otherwise, the resume will unwind to + // the caller. + mlir::Block *flattenUnwindHandler(mlir::Region &unwindRegion, + mlir::Location loc, + mlir::Block *insertBefore, + mlir::PatternRewriter &rewriter) const { + mlir::Block *unwindEntry = &unwindRegion.front(); + rewriter.inlineRegionBefore(unwindRegion, insertBefore); + return unwindEntry; } mlir::LogicalResult matchAndRewrite(cir::TryOp tryOp, mlir::PatternRewriter &rewriter) const override { - // Cleanup scopes must be lowered before the enclosing try so that - // EH cleanup inside them is properly handled. - // Fail the match so the pattern rewriter will process cleanup scopes first. - bool hasNestedCleanup = tryOp - ->walk([&](cir::CleanupScopeOp) { - return mlir::WalkResult::interrupt(); - }) - .wasInterrupted(); - if (hasNestedCleanup) + // Nested try ops and cleanup scopes must be flattened before the enclosing + // try so that EH cleanup inside them is properly handled. Fail the match so + // the pattern rewriter will process nested ops first. + bool hasNestedOps = + tryOp + ->walk([&](mlir::Operation *op) { + if (isa(op) && op != tryOp) + return mlir::WalkResult::interrupt(); + return mlir::WalkResult::advance(); + }) + .wasInterrupted(); + if (hasNestedOps) return mlir::failure(); - mlir::ArrayAttr handlers = tryOp.getHandlerTypesAttr(); - if (handlers && !handlers.empty()) - return tryOp->emitError( - "TryOp flattening with handlers is not yet implemented"); - mlir::OpBuilder::InsertionGuard guard(rewriter); - mlir::Block *afterBody = &tryOp.getTryRegion().back(); - - // Grab the collection of `cir.call exception`s to rewrite to - // `cir.try_call`. - llvm::SmallVector callsToRewrite; - tryOp.getTryRegion().walk([&](CallOp op) { - if (op.getNothrow()) - return; - - // Only grab calls within immediate closest TryOp scope. - if (op->getParentOfType() != tryOp) - return; - callsToRewrite.push_back(op); - }); + mlir::Location loc = tryOp.getLoc(); - if (!callsToRewrite.empty()) - llvm_unreachable( - "TryOpFlattening with try block that contains CallOps is NYI"); + mlir::ArrayAttr handlerTypes = tryOp.getHandlerTypesAttr(); + mlir::MutableArrayRef handlerRegions = + tryOp.getHandlerRegions(); - // Build try body. - mlir::Block *afterTry = buildTryBody(tryOp, rewriter); + // Collect throwing calls in the try body. + llvm::SmallVector callsToRewrite; + collectThrowingCalls(tryOp.getTryRegion(), callsToRewrite); - // Build handlers. - llvm::SmallVector landingPads; - buildHandlers(tryOp, rewriter, afterBody, afterTry, callsToRewrite, - landingPads); + // Collect resume ops from already-flattened cleanup scopes in the try body. + llvm::SmallVector resumeOpsToChain; + collectResumeOps(tryOp.getTryRegion(), resumeOpsToChain); - rewriter.eraseOp(tryOp); + // Split the current block and inline the try body. + mlir::Block *currentBlock = rewriter.getInsertionBlock(); + mlir::Block *continueBlock = + rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint()); - assert((landingPads.size() == callsToRewrite.size()) && - "expected matching number of entries"); + // Get references to try body blocks before inlining. + mlir::Block *bodyEntry = &tryOp.getTryRegion().front(); + mlir::Block *bodyExit = &tryOp.getTryRegion().back(); - // Quick block cleanup: no indirection to the post try block. - auto brOp = dyn_cast(afterTry->getTerminator()); - if (brOp && brOp.getDest()->hasNoPredecessors()) { - mlir::Block *srcBlock = brOp.getDest(); - rewriter.eraseOp(brOp); - rewriter.mergeBlocks(srcBlock, afterTry); + // Inline the try body region before the continue block. + rewriter.inlineRegionBefore(tryOp.getTryRegion(), continueBlock); + + // Branch from the current block to the body entry. + rewriter.setInsertionPointToEnd(currentBlock); + cir::BrOp::create(rewriter, loc, bodyEntry); + + // Replace the try body's yield terminator with a branch to continue. + if (auto bodyYield = dyn_cast(bodyExit->getTerminator())) { + rewriter.setInsertionPoint(bodyYield); + rewriter.replaceOpWithNewOp(bodyYield, continueBlock); } + // If there are no handlers, we're done. + if (!handlerTypes || handlerTypes.empty()) { + rewriter.eraseOp(tryOp); + return mlir::success(); + } + + // Build the catch handler blocks. + + // First, flatten all handler regions and collect the entry blocks. + llvm::SmallVector catchHandlerBlocks; + + for (const auto &[idx, typeAttr] : llvm::enumerate(handlerTypes)) { + mlir::Region &handlerRegion = handlerRegions[idx]; + + if (mlir::isa(typeAttr)) { + mlir::Block *unwindEntry = + flattenUnwindHandler(handlerRegion, loc, continueBlock, rewriter); + catchHandlerBlocks.push_back(unwindEntry); + } else { + mlir::Block *handlerEntry = flattenCatchHandler( + handlerRegion, continueBlock, loc, continueBlock, rewriter); + catchHandlerBlocks.push_back(handlerEntry); + } + } + + // Build the catch dispatch block. + mlir::Block *dispatchBlock = + buildCatchDispatchBlock(tryOp, handlerTypes, catchHandlerBlocks, loc, + catchHandlerBlocks.front(), rewriter); + + // Build a block to be the unwind desination for throwing calls and replace + // the calls with try_call ops. Note that the unwind block created here is + // something different than the unwind handler that we may have created + // above. The unwind handler continues unwinding after uncaught exceptions. + // This is the block that will eventually become the landing pad for invoke + // instructions. + bool hasCleanup = tryOp.getCleanup(); + if (!callsToRewrite.empty()) { + // Create a shared unwind block for all throwing calls. + mlir::Block *unwindBlock = buildUnwindBlock(dispatchBlock, hasCleanup, + loc, dispatchBlock, rewriter); + + for (cir::CallOp callOp : callsToRewrite) + replaceCallWithTryCall(callOp, unwindBlock, loc, rewriter); + } + + // Chain resume ops from inner cleanup scopes. + // Resume ops from already-flattened cleanup scopes within the try body + // should branch to the catch dispatch block instead of unwinding directly. + for (cir::ResumeOp resumeOp : resumeOpsToChain) { + mlir::Value ehToken = resumeOp.getEhToken(); + rewriter.setInsertionPoint(resumeOp); + rewriter.replaceOpWithNewOp( + resumeOp, mlir::ValueRange{ehToken}, dispatchBlock); + } + + // Finally, erase the original try op ---- + rewriter.eraseOp(tryOp); + return mlir::success(); } }; diff --git a/clang/test/CIR/Transforms/flatten-cleanup-scope-nyi.cir b/clang/test/CIR/Transforms/flatten-cleanup-scope-nyi.cir index 694a17f1568ef..63ed793b9cfd9 100644 --- a/clang/test/CIR/Transforms/flatten-cleanup-scope-nyi.cir +++ b/clang/test/CIR/Transforms/flatten-cleanup-scope-nyi.cir @@ -43,67 +43,6 @@ cir.func @test_all_cleanup_in_try() { cir.return } -// Test that we issue a diagnostic for an EH cleanup nested in a try with a -// catch all handlers. -cir.func @test_eh_cleanup_in_try_catchall() { - %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} - cir.call @ctor(%0) : (!cir.ptr) -> () - // expected-error @below {{TryOp flattening with handlers is not yet implemented}} - cir.try { - cir.cleanup.scope { - cir.call @doSomething(%0) : (!cir.ptr) -> () - cir.yield - } cleanup all { - cir.call @dtor(%0) nothrow : (!cir.ptr) -> () - cir.yield - } - cir.yield - } catch all (%eh_token : !cir.eh_token) { - %catch_token, %1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) - cir.cleanup.scope { - cir.yield - } cleanup eh { - cir.end_catch %catch_token : !cir.catch_token - cir.yield - } - cir.yield - } - cir.return -} - -// Test that we issue a diagnostic for an EH cleanup nested in a try with a -// catch and unwind handlers. -cir.func @test_eh_cleanup_in_try_catch_unwind() { - %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} - %1 = cir.alloca !s32i, !cir.ptr, ["e"] {alignment = 4 : i64} - cir.call @ctor(%0) : (!cir.ptr) -> () - // expected-error @below {{TryOp flattening with handlers is not yet implemented}} - cir.try { - cir.cleanup.scope { - cir.call @doSomething(%0) : (!cir.ptr) -> () - cir.yield - } cleanup all { - cir.call @dtor(%0) nothrow : (!cir.ptr) -> () - cir.yield - } - cir.yield - } catch [type #cir.global_view<@_ZTIi> : !cir.ptr] (%eh_token : !cir.eh_token) { - %catch_token, %2 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) - cir.cleanup.scope { - %3 = cir.load align(4) %2 : !cir.ptr, !s32i - cir.store align(4) %3, %1 : !s32i, !cir.ptr - cir.yield - } cleanup eh { - cir.end_catch %catch_token : !cir.catch_token - cir.yield - } - cir.yield - } unwind (%eh_token_1 : !cir.eh_token) { - cir.resume %eh_token_1 : !cir.eh_token - } - cir.return -} - // Test that we issue a diagnostic for throwing calls in the cleanup region // of a nested EH cleanup scope (the dtor is not nothrow). cir.func @test_nested_eh_cleanup() { @@ -205,35 +144,6 @@ cir.func @test_goto_in_nested_cleanup() { cir.return } -// Test that a try op with handlers nested inside a cleanup scope produces -// a diagnostic. The cleanup scope defers to the try op, which then fails -// because handler flattening is not yet implemented. -cir.func @test_try_with_handlers_in_cleanup() { - %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} - cir.call @ctor(%0) : (!cir.ptr) -> () - cir.cleanup.scope { - // expected-error @below {{TryOp flattening with handlers is not yet implemented}} - cir.try { - cir.call @doSomething(%0) : (!cir.ptr) -> () - cir.yield - } catch all (%eh_token : !cir.eh_token) { - %catch_token, %1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) - cir.cleanup.scope { - cir.yield - } cleanup eh { - cir.end_catch %catch_token : !cir.catch_token - cir.yield - } - cir.yield - } - cir.yield - } cleanup all { - cir.call @dtor(%0) nothrow : (!cir.ptr) -> () - cir.yield - } - cir.return -} - // Test that we issue a diagnostic for throwing calls in the cleanup region // of an EH cleanup scope. cir.func @test_throwing_call_in_eh_cleanup() { diff --git a/clang/test/CIR/Transforms/flatten-try-op.cir b/clang/test/CIR/Transforms/flatten-try-op.cir new file mode 100644 index 0000000000000..d761b602f1b12 --- /dev/null +++ b/clang/test/CIR/Transforms/flatten-try-op.cir @@ -0,0 +1,737 @@ +// RUN: cir-opt %s -cir-flatten-cfg -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +!s32i = !cir.int +!u8i = !cir.int +!void = !cir.void +!rec_SomeClass = !cir.record +!rec_exception = !cir.record + +// Test a simple try with no handlers and no throwing calls. +cir.func @test_try_no_handlers() { + %0 = cir.alloca !s32i, !cir.ptr, ["a", init] {alignment = 4 : i64} + cir.scope { + cir.try { + %1 = cir.const #cir.int<1> : !s32i + cir.store %1, %0 : !s32i, !cir.ptr + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_no_handlers() +// CHECK: %[[ALLOCA:.*]] = cir.alloca !s32i +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// CHECK: ^[[TRY_BODY]]: +// CHECK: %[[C1:.*]] = cir.const #cir.int<1> : !s32i +// CHECK: cir.store %[[C1]], %[[ALLOCA]] +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^[[SCOPE_EXIT:bb[0-9]+]] +// CHECK: ^[[SCOPE_EXIT]]: +// CHECK: cir.return + +// Test try-catch with catch all, throwing call in try body. +// The throwing call becomes try_call, and we get an unwind block, +// catch dispatch, and a catch-all handler. +cir.func @test_try_catch_all() { + cir.scope { + cir.try { + cir.call @mayThrow() : () -> () + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %catch_token, %exn_ptr = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_catch_all() +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @mayThrow() ^[[NORMAL:bb[0-9]+]], ^[[UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[UNWIND]]: +// CHECK: %[[EH_TOK:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_TOK]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_ALL]](%[[ET:.*]]: !cir.eh_token): +// CHECK: %[[CT:.*]], %[[EXN:.*]] = cir.begin_catch %[[ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch %[[CT]] : !cir.catch_token +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^[[SCOPE_EXIT:bb[0-9]+]] +// CHECK: ^[[SCOPE_EXIT]]: +// CHECK: cir.return + +// Test try-catch with typed handler and unwind. +// If the exception type doesn't match, control goes to the unwind handler +// which resumes unwinding. +cir.func @test_try_catch_typed_with_unwind() { + %0 = cir.alloca !cir.ptr, !cir.ptr>, ["e"] {alignment = 8 : i64} + cir.scope { + cir.try { + cir.call @mayThrow() : () -> () + cir.yield + } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr] (%eh_token : !cir.eh_token) { + %catch_token, %1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr>) + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } unwind (%eh_token : !cir.eh_token) { + cir.resume %eh_token : !cir.eh_token + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_catch_typed_with_unwind() +// CHECK: %[[E_ALLOCA:.*]] = cir.alloca !cir.ptr +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @mayThrow() ^[[NORMAL:bb[0-9]+]], ^[[UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[UNWIND]]: +// CHECK: %[[EH_TOK:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_TOK]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTISt9exception> : !cir.ptr) : ^[[CATCH_TYPED:bb[0-9]+]], +// CHECK: unwind : ^[[UNWIND_HANDLER:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_TYPED]](%[[CT_ET:.*]]: !cir.eh_token): +// CHECK: %[[CT:.*]], %[[EXN:.*]] = cir.begin_catch %[[CT_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr>) +// CHECK: cir.end_catch %[[CT]] : !cir.catch_token +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[UNWIND_HANDLER]](%[[UW_ET:.*]]: !cir.eh_token): +// CHECK: cir.resume %[[UW_ET]] : !cir.eh_token +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^{{.*}} +// CHECK: cir.return + +// Test try-catch with cleanup inside the try body. +// The cleanup scope is flattened first. The inner EH cleanup resume ops +// are chained to the catch dispatch block of the enclosing try. +cir.func @test_try_catch_with_cleanup() { + cir.scope { + %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} + cir.try { + cir.call @ctor(%0) : (!cir.ptr) -> () + cir.cleanup.scope { + cir.call @doSomething(%0) : (!cir.ptr) -> () + cir.yield + } cleanup all { + cir.call @dtor(%0) nothrow : (!cir.ptr) -> () + cir.yield + } + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %catch_token, %1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_catch_with_cleanup() +// CHECK: %[[C:.*]] = cir.alloca !rec_SomeClass +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @ctor(%[[C]]) ^[[AFTER_CTOR:bb[0-9]+]], ^[[OUTER_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[AFTER_CTOR]]: +// CHECK: cir.br ^[[CLEANUP_BODY:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_BODY]]: +// CHECK: cir.try_call @doSomething(%[[C]]) ^[[AFTER_DO:bb[0-9]+]], ^[[INNER_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[AFTER_DO]]: +// CHECK: cir.br ^[[NORMAL_CLEANUP:bb[0-9]+]] +// +// CHECK: ^[[NORMAL_CLEANUP]]: +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.br ^[[CLEANUP_EXIT:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_EXIT]]: +// CHECK: cir.br ^[[TRY_EXIT:bb[0-9]+]] +// +// CHECK: ^[[INNER_UNWIND]]: +// CHECK: %[[INNER_EH:.*]] = cir.eh.initiate cleanup : !cir.eh_token +// CHECK: cir.br ^[[EH_CLEANUP:bb[0-9]+]](%[[INNER_EH]] : !cir.eh_token) +// +// CHECK: ^[[EH_CLEANUP]](%[[EH_CT:.*]]: !cir.eh_token): +// CHECK: %[[CT:.*]] = cir.begin_cleanup %[[EH_CT]] : !cir.eh_token -> !cir.cleanup_token +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.end_cleanup %[[CT]] : !cir.cleanup_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_CT]] : !cir.eh_token) +// +// CHECK: ^[[TRY_EXIT]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[OUTER_UNWIND]]: +// CHECK: %[[CTOR_EH:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH]](%[[CTOR_EH]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_ALL]](%[[CA_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[CA_ET]] +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^{{.*}} +// CHECK: cir.return + +// Test try-catch within a cleanup scope. +// The try is nested inside a cleanup scope. If an exception is not caught +// by the try's handlers, the resume from the unwind handler should chain +// to the outer cleanup's EH handler. +cir.func @test_try_in_cleanup() { + %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} + %1 = cir.alloca !cir.ptr, !cir.ptr>, ["e"] {alignment = 8 : i64} + cir.call @ctor(%0) : (!cir.ptr) -> () + cir.cleanup.scope { + cir.scope { + cir.try { + cir.call @doSomething(%0) : (!cir.ptr) -> () + cir.yield + } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr] (%eh_token : !cir.eh_token) { + %catch_token, %2 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr>) + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } unwind (%eh_token : !cir.eh_token) { + cir.resume %eh_token : !cir.eh_token + } + } + cir.yield + } cleanup all { + cir.call @dtor(%0) nothrow : (!cir.ptr) -> () + cir.yield + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_in_cleanup() +// CHECK: %[[C:.*]] = cir.alloca !rec_SomeClass +// CHECK: %[[E:.*]] = cir.alloca !cir.ptr +// CHECK: cir.call @ctor(%[[C]]) +// CHECK: cir.br ^[[OUTER_CLEANUP_BODY:bb[0-9]+]] +// +// CHECK: ^[[OUTER_CLEANUP_BODY]]: +// CHECK: cir.br ^[[SCOPE_ENTER:bb[0-9]+]] +// +// CHECK: ^[[SCOPE_ENTER]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @doSomething(%[[C]]) ^[[NORMAL:bb[0-9]+]], ^[[TRY_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[TRY_CONT:bb[0-9]+]] +// +// CHECK: ^[[TRY_UNWIND]]: +// CHECK: %[[TRY_EH:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[TRY_EH]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTISt9exception> : !cir.ptr) : ^[[CATCH:bb[0-9]+]], +// CHECK: unwind : ^[[UNWIND_HANDLER:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH]](%[[CATCH_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[CATCH_ET]] +// CHECK: cir.end_catch +// CHECK: cir.br ^[[TRY_CONT]] +// +// CHECK: ^[[UNWIND_HANDLER]](%[[UW_ET:.*]]: !cir.eh_token): +// CHECK: cir.br ^[[OUTER_EH_CLEANUP:bb[0-9]+]](%[[UW_ET]] : !cir.eh_token) +// +// CHECK: ^[[TRY_CONT]]: +// CHECK: cir.br ^[[SCOPE_EXIT:bb[0-9]+]] +// +// CHECK: ^[[SCOPE_EXIT]]: +// CHECK: cir.br ^[[NORMAL_CLEANUP:bb[0-9]+]] +// +// CHECK: ^[[NORMAL_CLEANUP]]: +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.br ^[[CLEANUP_EXIT:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_EXIT]]: +// CHECK: cir.br ^[[RETURN:bb[0-9]+]] +// +// CHECK: ^[[OUTER_EH_CLEANUP]](%[[OEH_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}} = cir.begin_cleanup %[[OEH_ET]] +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.end_cleanup +// CHECK: cir.resume %[[OEH_ET]] : !cir.eh_token +// +// CHECK: ^[[RETURN]]: +// CHECK: cir.return + +// Test try with catch all and no throwing calls. +// The try body doesn't have throwing calls, so no try_call/unwind blocks are +// needed. The handlers are still built but won't be reachable. +cir.func @test_try_catch_all_no_throwing_calls() { + cir.scope { + cir.try { + %0 = cir.const #cir.int<42> : !s32i + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %catch_token, %exn_ptr = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_catch_all_no_throwing_calls() +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: %{{.*}} = cir.const #cir.int<42> : !s32i +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// Catch dispatch (unreachable since there are no throwing calls). +// CHECK: ^[[DISPATCH:bb[0-9]+]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// Catch-all handler (unreachable). +// CHECK: ^[[CATCH_ALL]](%[[ET:.*]]: !cir.eh_token): +// CHECK: %[[CT:.*]], %{{.*}} = cir.begin_catch %[[ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch %[[CT]] : !cir.catch_token +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^[[SCOPE_EXIT:bb[0-9]+]] +// CHECK: ^[[SCOPE_EXIT]]: +// CHECK: cir.return + +// Test try-catch with multiple typed handlers and catch-all. +cir.func @test_try_multiple_handlers() { + cir.scope { + cir.try { + cir.call @mayThrow() : () -> () + cir.yield + } catch [type #cir.global_view<@_ZTIi> : !cir.ptr] (%eh_token : !cir.eh_token) { + %ct1, %exn1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct1 : !cir.catch_token + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %ct2, %exn2 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct2 : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_multiple_handlers() +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @mayThrow() ^[[NORMAL:bb[0-9]+]], ^[[UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[UNWIND]]: +// CHECK: %[[EH_TOK:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_TOK]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTIi> : !cir.ptr) : ^[[CATCH_INT:bb[0-9]+]], +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_INT]](%[[INT_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[INT_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CATCH_ALL]](%[[ALL_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[ALL_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^{{.*}} +// CHECK: cir.return + +// Test nested try ops. +// The inner try is flattened first. Its unwind handler's resume is then +// chained to the outer try's catch dispatch when the outer try is flattened. +cir.func @test_nested_try() { + cir.scope { + cir.try { + cir.try { + cir.call @mayThrow() : () -> () + cir.yield + } catch [type #cir.global_view<@_ZTIi> : !cir.ptr] (%eh_token : !cir.eh_token) { + %ct, %exn = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct : !cir.catch_token + cir.yield + } unwind (%eh_token : !cir.eh_token) { + cir.resume %eh_token : !cir.eh_token + } + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %ct, %exn = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_nested_try() +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[OUTER_BODY:bb[0-9]+]] +// +// CHECK: ^[[OUTER_BODY]]: +// CHECK: cir.br ^[[INNER_BODY:bb[0-9]+]] +// +// CHECK: ^[[INNER_BODY]]: +// CHECK: cir.try_call @mayThrow() ^[[INNER_NORMAL:bb[0-9]+]], ^[[INNER_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[INNER_NORMAL]]: +// CHECK: cir.br ^[[INNER_CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[INNER_UNWIND]]: +// CHECK: %[[IEH:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[INNER_DISPATCH:bb[0-9]+]](%[[IEH]] : !cir.eh_token) +// +// CHECK: ^[[INNER_DISPATCH]](%[[ID_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[ID_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTIi> : !cir.ptr) : ^[[INNER_CATCH:bb[0-9]+]], +// CHECK: unwind : ^[[INNER_UW_HANDLER:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[INNER_CATCH]](%[[IC_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[IC_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[INNER_CONTINUE]] +// +// CHECK: ^[[INNER_UW_HANDLER]](%[[IUW_ET:.*]]: !cir.eh_token): +// CHECK: cir.br ^[[OUTER_DISPATCH:bb[0-9]+]](%[[IUW_ET]] : !cir.eh_token) +// +// CHECK: ^[[INNER_CONTINUE]]: +// CHECK: cir.br ^[[OUTER_CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[OUTER_DISPATCH]](%[[OD_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[OD_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[OUTER_CATCH:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[OUTER_CATCH]](%[[OC_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[OC_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[OUTER_CONTINUE]] +// +// CHECK: ^[[OUTER_CONTINUE]]: +// CHECK: cir.br ^{{.*}} +// CHECK: cir.return + +// Test a try op with handlers nested inside a cleanup scope and a cleanup +// scope inside a catch handler. This is the form of the catch handler that will +// actually be generated. The representations above are all simplifications. +cir.func @test_try_with_handlers_in_cleanup() { + %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} + cir.call @ctor(%0) : (!cir.ptr) -> () + cir.cleanup.scope { + cir.try { + cir.call @doSomething(%0) : (!cir.ptr) -> () + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %catch_token, %1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.cleanup.scope { + cir.yield + } cleanup all { + cir.end_catch %catch_token : !cir.catch_token + cir.yield + } + cir.yield + } + cir.yield + } cleanup all { + cir.call @dtor(%0) nothrow : (!cir.ptr) -> () + cir.yield + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_with_handlers_in_cleanup() +// CHECK: %[[C:.*]] = cir.alloca !rec_SomeClass +// CHECK: cir.call @ctor(%[[C]]) +// CHECK: cir.br ^[[CLEANUP_BODY:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_BODY]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @doSomething(%[[C]]) ^[[NORMAL:bb[0-9]+]], ^[[UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[TRY_CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[UNWIND]]: +// CHECK: %[[EH_TOK:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_TOK]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_ALL]](%[[ET:.*]]: !cir.eh_token): +// CHECK: %[[CATCH_TOK:.*]], %{{.*}} = cir.begin_catch %[[ET]] +// CHECK: cir.br ^[[INNER_CLEANUP_BODY:bb[0-9]+]] +// CHECK: ^[[INNER_CLEANUP_BODY]]: +// CHECK: cir.br ^[[NORMAL_CLEANUP:bb[0-9]+]] +// CHECK: ^[[NORMAL_CLEANUP]]: +// CHECK: cir.end_catch %[[CATCH_TOK]] +// CHECK: cir.br ^[[CLEANUP_EXIT:bb[0-9]+]] +// CHECK: ^[[CLEANUP_EXIT]]: +// CHECK: cir.br ^[[CATCH_EXIT:bb[0-9]+]] +// CHECK: ^[[CATCH_EXIT]]: +// CHECK: cir.br ^[[TRY_CONTINUE]] +// +// CHECK: ^[[TRY_CONTINUE]]: +// CHECK: cir.br ^{{.*}} +// CHECK: cir.call @dtor(%[[C]]) nothrow +// +// CHECK: cir.return + +// Test nested try ops with a cleanup scope in the outer try body. +// The inner try's unwind handler must execute the cleanup (dtor) before +// the exception reaches the outer try's catch dispatch. +cir.func @test_nested_try_with_cleanup() { + %0 = cir.alloca !rec_SomeClass, !cir.ptr, ["c", init] {alignment = 4 : i64} + cir.scope { + cir.try { + cir.call @ctor(%0) : (!cir.ptr) -> () + cir.cleanup.scope { + cir.try { + cir.call @doSomething(%0) : (!cir.ptr) -> () + cir.yield + } catch [type #cir.global_view<@_ZTIi> : !cir.ptr] (%eh_token : !cir.eh_token) { + %ct, %exn = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct : !cir.catch_token + cir.yield + } unwind (%eh_token : !cir.eh_token) { + cir.resume %eh_token : !cir.eh_token + } + cir.yield + } cleanup all { + cir.call @dtor(%0) nothrow : (!cir.ptr) -> () + cir.yield + } + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %ct, %exn = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_nested_try_with_cleanup() +// CHECK: %[[C:.*]] = cir.alloca !rec_SomeClass +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @ctor(%[[C]]) ^[[AFTER_CTOR:bb[0-9]+]], ^[[CTOR_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[AFTER_CTOR]]: +// CHECK: cir.br ^[[CLEANUP_BODY:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_BODY]]: +// CHECK: cir.br ^[[INNER_TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[INNER_TRY_BODY]]: +// CHECK: cir.try_call @doSomething(%[[C]]) ^[[INNER_NORMAL:bb[0-9]+]], ^[[INNER_UNWIND:bb[0-9]+]] +// +// CHECK: ^[[INNER_NORMAL]]: +// CHECK: cir.br ^[[INNER_CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[INNER_UNWIND]]: +// CHECK: %[[IEH:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[INNER_DISPATCH:bb[0-9]+]](%[[IEH]] : !cir.eh_token) +// +// CHECK: ^[[INNER_DISPATCH]](%[[ID_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[ID_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTIi> : !cir.ptr) : ^[[INNER_CATCH:bb[0-9]+]], +// CHECK: unwind : ^[[INNER_UW_HANDLER:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[INNER_CATCH]](%[[IC_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[IC_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[INNER_CONTINUE]] +// +// The inner unwind handler goes through the EH cleanup (dtor) before +// reaching the outer try's catch dispatch. +// CHECK: ^[[INNER_UW_HANDLER]](%[[IUW_ET:.*]]: !cir.eh_token): +// CHECK: cir.br ^[[EH_CLEANUP:bb[0-9]+]](%[[IUW_ET]] : !cir.eh_token) +// +// The continuation path after the inner try catches an exception branches to +// the normal outer cleanup. +// CHECK: ^[[INNER_CONTINUE]]: +// CHECK: cir.br ^[[NORMAL_CLEANUP:bb[0-9]+]] +// +// CHECK: ^[[NORMAL_CLEANUP]]: +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.br ^[[CLEANUP_EXIT:bb[0-9]+]] +// +// CHECK: ^[[CLEANUP_EXIT]]: +// CHECK: cir.br ^[[TRY_EXIT:bb[0-9]+]] +// +// EH cleanup: the cleanup (dtor) runs before unwinding to the outer dispatch. +// CHECK: ^[[EH_CLEANUP]](%[[EH_ET:.*]]: !cir.eh_token): +// CHECK: %[[CT:.*]] = cir.begin_cleanup %[[EH_ET]] : !cir.eh_token -> !cir.cleanup_token +// CHECK: cir.call @dtor(%[[C]]) nothrow +// CHECK: cir.end_cleanup %[[CT]] : !cir.cleanup_token +// CHECK: cir.br ^[[OUTER_DISPATCH:bb[0-9]+]](%[[EH_ET]] : !cir.eh_token) +// +// CHECK: ^[[TRY_EXIT]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// Ctor's unwind goes directly to outer dispatch (cleanup scope not yet entered). +// CHECK: ^[[CTOR_UNWIND]]: +// CHECK: %[[CTOR_EH:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[OUTER_DISPATCH]](%[[CTOR_EH]] : !cir.eh_token) +// +// CHECK: ^[[OUTER_DISPATCH]](%[[OD_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[OD_ET]] : !cir.eh_token [ +// CHECK: catch_all : ^[[OUTER_CATCH:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[OUTER_CATCH]](%[[OC_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[OC_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^[[RETURN:bb[0-9]+]] +// CHECK: ^[[RETURN]]: +// CHECK: cir.return + +// Test try-catch with multiple typed handlers and a catch-all. +cir.func @test_try_multiple_typed_and_catch_all() { + cir.scope { + cir.try { + cir.call @mayThrow() : () -> () + cir.yield + } catch [type #cir.global_view<@_ZTISt9exception> : !cir.ptr] (%eh_token : !cir.eh_token) { + %ct1, %exn1 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr>) + cir.end_catch %ct1 : !cir.catch_token + cir.yield + } catch [type #cir.global_view<@_ZTIi> : !cir.ptr] (%eh_token : !cir.eh_token) { + %ct2, %exn2 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct2 : !cir.catch_token + cir.yield + } catch all (%eh_token : !cir.eh_token) { + %ct3, %exn3 = cir.begin_catch %eh_token : !cir.eh_token -> (!cir.catch_token, !cir.ptr) + cir.end_catch %ct3 : !cir.catch_token + cir.yield + } + } + cir.return +} + +// CHECK-LABEL: cir.func @test_try_multiple_typed_and_catch_all() +// CHECK: cir.br ^[[SCOPE:bb[0-9]+]] +// +// CHECK: ^[[SCOPE]]: +// CHECK: cir.br ^[[TRY_BODY:bb[0-9]+]] +// +// CHECK: ^[[TRY_BODY]]: +// CHECK: cir.try_call @mayThrow() ^[[NORMAL:bb[0-9]+]], ^[[UNWIND:bb[0-9]+]] +// +// CHECK: ^[[NORMAL]]: +// CHECK: cir.br ^[[CONTINUE:bb[0-9]+]] +// +// CHECK: ^[[UNWIND]]: +// CHECK: %[[EH_TOK:.*]] = cir.eh.initiate : !cir.eh_token +// CHECK: cir.br ^[[DISPATCH:bb[0-9]+]](%[[EH_TOK]] : !cir.eh_token) +// +// CHECK: ^[[DISPATCH]](%[[DISP_ET:.*]]: !cir.eh_token): +// CHECK: cir.eh.dispatch %[[DISP_ET]] : !cir.eh_token [ +// CHECK: catch(#cir.global_view<@_ZTISt9exception> : !cir.ptr) : ^[[CATCH_EXN:bb[0-9]+]], +// CHECK: catch(#cir.global_view<@_ZTIi> : !cir.ptr) : ^[[CATCH_INT:bb[0-9]+]], +// CHECK: catch_all : ^[[CATCH_ALL:bb[0-9]+]] +// CHECK: ] +// +// CHECK: ^[[CATCH_EXN]](%[[EXN_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[EXN_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr>) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CATCH_INT]](%[[INT_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[INT_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CATCH_ALL]](%[[ALL_ET:.*]]: !cir.eh_token): +// CHECK: %{{.*}}, %{{.*}} = cir.begin_catch %[[ALL_ET]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr) +// CHECK: cir.end_catch +// CHECK: cir.br ^[[CONTINUE]] +// +// CHECK: ^[[CONTINUE]]: +// CHECK: cir.br ^[[RETURN:bb[0-9]+]] +// CHECK: ^[[RETURN]]: +// CHECK: cir.return + +cir.func private @mayThrow() +cir.func private @ctor(!cir.ptr) +cir.func private @dtor(!cir.ptr) attributes {nothrow} +cir.func private @doSomething(!cir.ptr) +cir.global "private" constant external @_ZTISt9exception : !cir.ptr +cir.global "private" constant external @_ZTIi : !cir.ptr From 3d889c464eb19f3c9d5dd00caab37be19a81efa3 Mon Sep 17 00:00:00 2001 From: Ben Dunkin <108952361+bdunkin@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:30:00 -0800 Subject: [PATCH 36/58] [clang-format] Fix SpaceBeforeParens with explicit template instantiations (#183183) This fixes explicit template instantiated functions not having spaces added/removed based on the value of `SpaceBeforeParens`. Attribution Note - I have been authorized to contribute this change on behalf of my company: ArenaNet LLC --- clang/lib/Format/TokenAnnotator.cpp | 19 ++++++++++--------- clang/unittests/Format/FormatTest.cpp | 4 ++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 34e81bbc97578..1b588435d6302 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4913,6 +4913,15 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return true; // Space before parentheses common for all languages if (Right.is(tok::l_paren)) { + // Function declaration or definition + if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) { + if (spaceRequiredBeforeParens(Right)) + return true; + const auto &Options = Style.SpaceBeforeParensOptions; + return Line.mightBeFunctionDefinition() + ? Options.AfterFunctionDefinitionName + : Options.AfterFunctionDeclarationName; + } if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen)) return spaceRequiredBeforeParens(Right); if (Left.isOneOf(TT_RequiresClause, @@ -4958,15 +4967,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, // SpaceBeforeParensOptions if (Right.is(TT_OverloadedOperatorLParen)) return spaceRequiredBeforeParens(Right); - // Function declaration or definition - if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) { - if (spaceRequiredBeforeParens(Right)) - return true; - const auto &Options = Style.SpaceBeforeParensOptions; - return Line.mightBeFunctionDefinition() - ? Options.AfterFunctionDefinitionName - : Options.AfterFunctionDeclarationName; - } + // Lambda if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) && Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 43633b582a8ab..dfc21bcefad53 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17334,6 +17334,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("void f(int a, T b) {}", SpaceFuncDecl); verifyFormat("void __attribute__((asdf)) f(int a, T b) {}", SpaceFuncDecl); verifyFormat("A::A() : a(1) {}", SpaceFuncDecl); + verifyFormat("template <> void A (C x);", SpaceFuncDecl); + verifyFormat("template <> void A(C x) {}", SpaceFuncDecl); verifyFormat("void f () __attribute__((asdf));", SpaceFuncDecl); verifyFormat("void __attribute__((asdf)) f ();", SpaceFuncDecl); verifyFormat("#define A(x) x", SpaceFuncDecl); @@ -17370,6 +17372,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("void f (int a, T b) {}", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f (int a, T b) {}", SpaceFuncDef); verifyFormat("A::A () : a(1) {}", SpaceFuncDef); + verifyFormat("template <> void A(C x);", SpaceFuncDef); + verifyFormat("template <> void A (C x) {}", SpaceFuncDef); verifyFormat("void f() __attribute__((asdf));", SpaceFuncDef); verifyFormat("void __attribute__((asdf)) f();", SpaceFuncDef); verifyFormat("#define A(x) x", SpaceFuncDef); From 4f05592bc01ca0252e904a59f8e321e254cd0473 Mon Sep 17 00:00:00 2001 From: Srividya Sundaram Date: Fri, 27 Feb 2026 11:30:46 -0800 Subject: [PATCH 37/58] [Driver][SYCL] Add tests for -Xarch_ option forwarding to SYCL JIT compilation. (#178025) This change adds test coverage to verify that options passed via `-Xarch_