From 7860f9b13548e82807d732c5f92391dd125c2745 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 13 Oct 2025 20:24:55 -0700 Subject: [PATCH] [sroa][profcheck] Propagate profile in `unfoldGEPSelect` --- llvm/lib/Transforms/Scalar/SROA.cpp | 18 ++++++++++++--- llvm/test/Transforms/SROA/phi-gep.ll | 29 +++++++++++++++++++------ llvm/test/Transforms/SROA/select-gep.ll | 19 +++++++++++++--- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 1068df52c811a..d2f09e9f3c639 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -118,9 +118,13 @@ STATISTIC( STATISTIC(NumDeleted, "Number of instructions deleted"); STATISTIC(NumVectorized, "Number of vectorized aggregates"); +namespace llvm { /// Disable running mem2reg during SROA in order to test or debug SROA. static cl::opt SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false), cl::Hidden); +extern cl::opt ProfcheckDisableMetadataFixes; +} // namespace llvm + namespace { class AllocaSliceRewriter; @@ -1777,7 +1781,8 @@ static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, } Value *V = IRB.CreateSelect(SI.getCondition(), TL, FL, - LI.getName() + ".sroa.speculated", &SI); + LI.getName() + ".sroa.speculated", + ProfcheckDisableMetadataFixes ? nullptr : &SI); LLVM_DEBUG(dbgs() << " speculated to: " << *V << "\n"); LI.replaceAllUsesWith(V); @@ -4360,10 +4365,13 @@ class AggLoadStoreRewriter : public InstVisitor { }; Value *Cond, *True, *False; + Instruction *MDFrom = nullptr; if (auto *SI = dyn_cast(Sel)) { Cond = SI->getCondition(); True = SI->getTrueValue(); False = SI->getFalseValue(); + if (!ProfcheckDisableMetadataFixes) + MDFrom = SI; } else { Cond = Sel->getOperand(0); True = ConstantInt::get(Sel->getType(), 1); @@ -4383,8 +4391,12 @@ class AggLoadStoreRewriter : public InstVisitor { IRB.CreateGEP(Ty, FalseOps[0], ArrayRef(FalseOps).drop_front(), False->getName() + ".sroa.gep", NW); - Value *NSel = - IRB.CreateSelect(Cond, NTrue, NFalse, Sel->getName() + ".sroa.sel"); + Value *NSel = MDFrom + ? IRB.CreateSelect(Cond, NTrue, NFalse, + Sel->getName() + ".sroa.sel", MDFrom) + : IRB.CreateSelectWithUnknownProfile( + Cond, NTrue, NFalse, DEBUG_TYPE, + Sel->getName() + ".sroa.sel"); Visited.erase(&GEPI); GEPI.replaceAllUsesWith(NSel); GEPI.eraseFromParent(); diff --git a/llvm/test/Transforms/SROA/phi-gep.ll b/llvm/test/Transforms/SROA/phi-gep.ll index 776624c0798cf..45c3bbdeb3897 100644 --- a/llvm/test/Transforms/SROA/phi-gep.ll +++ b/llvm/test/Transforms/SROA/phi-gep.ll @@ -1,9 +1,12 @@ -; 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 -S -passes='sroa' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG ; RUN: opt -S -passes='sroa' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG %pair = type { i32, i32 } +;. +; CHECK: @g = global %pair zeroinitializer, align 4 +;. define i32 @test_sroa_phi_gep(i1 %cond) { ; CHECK-LABEL: @test_sroa_phi_gep( ; CHECK-NEXT: entry: @@ -334,18 +337,18 @@ exit: unreachable } -define void @test_sroa_gep_phi_select_same_block(i1 %c1, i1 %c2, ptr %ptr) { +define void @test_sroa_gep_phi_select_same_block(i1 %c1, i1 %c2, ptr %ptr) !prof !0 { ; CHECK-LABEL: @test_sroa_gep_phi_select_same_block( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]] ; CHECK: while.body: ; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ] -; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]] +; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]], !prof [[PROF1:![0-9]+]] ; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1 ; CHECK-NEXT: [[PTR_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PTR]], i64 1 -; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]] -; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]] +; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]], !prof [[PROF1]] +; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]], !prof [[PROF2:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -355,9 +358,9 @@ entry: while.body: %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ] - %select = select i1 %c1, ptr %phi, ptr %ptr + %select = select i1 %c1, ptr %phi, ptr %ptr, !prof !1 %gep = getelementptr inbounds %pair, ptr %select, i64 1 - br i1 %c2, label %exit, label %while.body + br i1 %c2, label %exit, label %while.body, !prof !2 exit: ret void @@ -747,6 +750,18 @@ declare ptr @foo() declare i32 @__gxx_personality_v0(...) declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) + +!0 = !{!"function_entry_count", i32 10} +!1 = !{!"branch_weights", i32 3, i32 5} +!2 = !{!"branch_weights", i32 7, i32 11} + +;. +; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +;. +; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i32 10} +; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 5} +; CHECK: [[PROF2]] = !{!"branch_weights", i32 7, i32 11} +;. ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; CHECK-MODIFY-CFG: {{.*}} ; CHECK-PRESERVE-CFG: {{.*}} diff --git a/llvm/test/Transforms/SROA/select-gep.ll b/llvm/test/Transforms/SROA/select-gep.ll index b48b0f77aa991..a701d78ff3f7a 100644 --- a/llvm/test/Transforms/SROA/select-gep.ll +++ b/llvm/test/Transforms/SROA/select-gep.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 -S -passes='sroa' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG ; RUN: opt -S -passes='sroa' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG @@ -203,10 +203,10 @@ define i32 @test_select_idx_mem2reg(i1 %c) { ; Test gep with a select-like zext index unfolding on an alloca that is ; splittable and promotable. -define i64 @test_select_like_zext_idx_mem2reg(i1 %c) { +define i64 @test_select_like_zext_idx_mem2reg(i1 %c) !prof !0 { ; CHECK-LABEL: @test_select_like_zext_idx_mem2reg( ; CHECK-NEXT: [[IDX:%.*]] = zext i1 [[C:%.*]] to i64 -; CHECK-NEXT: [[RES:%.*]] = select i1 [[C]], i64 2, i64 1 +; CHECK-NEXT: [[RES:%.*]] = select i1 [[C]], i64 2, i64 1, !prof [[PROF1:![0-9]+]] ; CHECK-NEXT: ret i64 [[RES]] ; %alloca = alloca [2 x i64], align 8 @@ -352,3 +352,16 @@ define i32 @test_select_idx_not_constant3(i1 %c, ptr %p, i64 %arg) { %res = load i32, ptr %gep, align 4 ret i32 %res } + +!0 = !{!"function_entry_count", i32 10} +;. +; CHECK-PRESERVE-CFG: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +;. +; CHECK-MODIFY-CFG: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +;. +; CHECK-PRESERVE-CFG: [[META0:![0-9]+]] = !{!"function_entry_count", i32 10} +; CHECK-PRESERVE-CFG: [[PROF1]] = !{!"unknown", !"sroa"} +;. +; CHECK-MODIFY-CFG: [[META0:![0-9]+]] = !{!"function_entry_count", i32 10} +; CHECK-MODIFY-CFG: [[PROF1]] = !{!"unknown", !"sroa"} +;.