diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 72e1131a54a86..e88fcdd262f35 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -115,6 +115,8 @@ GVNEnableSplitBackedgeInLoadPRE("enable-split-backedge-in-load-pre", static cl::opt GVNEnableMemDep("enable-gvn-memdep", cl::init(true)); static cl::opt GVNEnableMemorySSA("enable-gvn-memoryssa", cl::init(false)); +static cl::opt GVNSkipZeroEntryCount("gvn-skip-zero-entry-count", + cl::init(false)); static cl::opt MaxNumDeps( "gvn-max-num-deps", cl::Hidden, cl::init(100), @@ -894,6 +896,17 @@ PreservedAnalyses GVNPass::run(Function &F, FunctionAnalysisManager &AM) { MSSA = &AM.getResult(F); } auto &ORE = AM.getResult(F); + + // Skip the pass if function has zero entry count in PGO. + // This indicates that the function is never executed according to the profile + // data. + auto EntryCount = F.getEntryCount(); + if (GVNSkipZeroEntryCount && EntryCount && EntryCount->getCount() == 0) { + LLVM_DEBUG(dbgs() << "GVN: Skipping function '" << F.getName() + << "' with zero profile entry count\n"); + return PreservedAnalyses::all(); + } + bool Changed = runImpl(F, AC, DT, TLI, AA, MemDep, LI, &ORE, MSSA ? &MSSA->getMSSA() : nullptr); if (!Changed) diff --git a/llvm/test/Transforms/GVN/skip-gvn-blockfreq.ll b/llvm/test/Transforms/GVN/skip-gvn-blockfreq.ll new file mode 100644 index 0000000000000..c1a33bbda1aa4 --- /dev/null +++ b/llvm/test/Transforms/GVN/skip-gvn-blockfreq.ll @@ -0,0 +1,41 @@ +; Test that GVN is skipped when function has zero entry count in PGO +; RUN: opt -passes='gvn' -gvn-skip-zero-entry-count=true -S < %s | FileCheck %s + +; Function with ZERO entry count - GVN should skip this function +; The redundant computation should remain because GVN doesn't run +; CHECK-LABEL: @zero_freq_function( +; CHECK-NEXT: entry: +; CHECK-NEXT: %a = add i32 %x, 1 +; CHECK-NEXT: %b = add i32 %a, 2 +; CHECK-NEXT: %c = add i32 %a, 2 +; CHECK-NEXT: %result = add i32 %b, %c +; CHECK-NEXT: ret i32 %result +define i32 @zero_freq_function(i32 %x) !prof !0 { +entry: + %a = add i32 %x, 1 + %b = add i32 %a, 2 + %c = add i32 %a, 2 ; Redundant - but GVN should not optimize due to zero freq + %result = add i32 %b, %c + ret i32 %result +} + +; Function with NON-ZERO entry count - GVN should run normally +; The redundant computation should be eliminated by GVN +; CHECK-LABEL: @nonzero_freq_function( +; CHECK-NEXT: entry: +; CHECK-NEXT: %a = add i32 %x, 1 +; CHECK-NEXT: %b = add i32 %a, 2 +; CHECK-NEXT: %result = add i32 %b, %b +; CHECK-NEXT: ret i32 %result +define i32 @nonzero_freq_function(i32 %x) !prof !1 { +entry: + %a = add i32 %x, 1 + %b = add i32 %a, 2 + %c = add i32 %a, 2 ; Redundant - GVN optimizes this + %result = add i32 %b, %c + ret i32 %result +} + +!0 = !{!"function_entry_count", i64 0} ; Zero frequency +!1 = !{!"function_entry_count", i64 1000} ; Non-zero frequency +