[llvm] 097e0e1 - llvm-reduce: Add pass to sink defs to uses (#170317)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 4 12:33:07 PST 2025
Author: Matt Arsenault
Date: 2025-12-04T21:33:03+01:00
New Revision: 097e0e116aa42f114d6e7dd166069f90d85cce97
URL: https://github.com/llvm/llvm-project/commit/097e0e116aa42f114d6e7dd166069f90d85cce97
DIFF: https://github.com/llvm/llvm-project/commit/097e0e116aa42f114d6e7dd166069f90d85cce97.diff
LOG: llvm-reduce: Add pass to sink defs to uses (#170317)
The intent is to reduce live ranges and reduce
the impact on later scheduling on the testcase.
Added:
llvm/test/tools/llvm-reduce/reduce-sink-defs-to-uses.ll
llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp
llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h
Modified:
llvm/tools/llvm-reduce/CMakeLists.txt
llvm/tools/llvm-reduce/DeltaManager.cpp
llvm/tools/llvm-reduce/DeltaPasses.def
llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-reduce/reduce-sink-defs-to-uses.ll b/llvm/test/tools/llvm-reduce/reduce-sink-defs-to-uses.ll
new file mode 100644
index 0000000000000..5c972640ac200
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/reduce-sink-defs-to-uses.ll
@@ -0,0 +1,264 @@
+; Test that llvm-reduce can move def instructions down to uses.
+;
+; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=sink-defs-to-uses --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t
+; RUN: FileCheck --check-prefixes=CHECK,RESULT %s < %t
+
+declare i32 @leaf()
+declare void @func()
+declare void @use(i32)
+declare void @use0(i32)
+declare void @use1(i32)
+declare void @use2(i32)
+declare i32 @leaf_with_arg(i32)
+
+; CHECK-LABEL: define i32 @sink_leaf_to_ret() {
+; INTERESTING: call i32 @leaf()
+
+; RESULT-NEXT: call void @func()
+; RESULT-NEXT: %ret = call i32 @leaf()
+; RESULT-NEXT: ret i32 %ret
+define i32 @sink_leaf_to_ret() {
+ %ret = call i32 @leaf()
+ call void @func()
+ ret i32 %ret
+}
+
+; CHECK-LABEL: define i32 @no_sink_leaf_to_ret() {
+; INTERESTING: call i32 @leaf()
+; INTERESTING: call void @func()
+
+; RESULT: %ret = call i32 @leaf()
+; RESULT-NEXT: call void @func()
+; RESULT-NEXT: ret i32 %ret
+define i32 @no_sink_leaf_to_ret() {
+ %ret = call i32 @leaf()
+ call void @func()
+ ret i32 %ret
+}
+
+; CHECK-LABEL: define i32 @sink_across_trivial_block() {
+; RESULT: {{^}}entry:
+; RESULT-NEXT: br label %ret
+; RESULT: {{^}}ret:
+; RESULT-NEXT: call void @func
+; RESULT-NEXT: %val = call i32 @leaf()
+; RESULT-NEXT: ret i32 %val
+define i32 @sink_across_trivial_block() {
+entry:
+ %val = call i32 @leaf()
+ br label %ret
+
+ret:
+ call void @func()
+ ret i32 %val
+}
+
+; CHECK-LABEL: define i32 @cannot_sink_phi_def(
+; INTERESTING: phi i32
+
+; RESULT: {{^}}b:
+; RESULT-NEXT: %phi = phi i32
+; RESULT-NEXT: call void @func(
+; RESULT-NEXT: ret i32 %phi
+define i32 @cannot_sink_phi_def(i1 %cond) {
+entry:
+ br i1 %cond, label %a, label %b
+
+a:
+ br label %b
+
+b:
+ %phi = phi i32 [ 0, %entry ], [ 1, %a ]
+ call void @func()
+ ret i32 %phi
+}
+
+; CHECK-LABEL: define i32 @cannot_sink_phi_use(
+; INTERESTING: phi i32
+define i32 @cannot_sink_phi_use(ptr %arg) {
+entry:
+ call void @func()
+ br label %loop
+
+loop:
+ %phi = phi i32 [ 0, %entry ], [ %add, %loop ]
+ call void @func()
+ %def0 = call i32 @leaf()
+ call void @func()
+ %add = add i32 %phi, 1
+ %loop.cond = load volatile i1, ptr %arg
+ br i1 %loop.cond, label %loop, label %exit
+
+exit:
+ ret i32 %phi
+}
+
+; CHECK-LABEL: define i32 @cannot_sink_past_other_use(
+; INTERESTING: call i32 @leaf
+
+; RESULT-NEXT: %val = call i32
+; RESULT-NEXT: call void @use(i32 %val)
+; RESULT-NEXT: ret i32 %val
+define i32 @cannot_sink_past_other_use() {
+ %val = call i32 @leaf()
+ call void @use(i32 %val)
+ ret i32 %val
+}
+
+; CHECK-LABEL: define void @no_sink_alloca(
+; CHECK-NEXT: alloca
+; RESULT-NEXT: call void @func
+; RESULT-NEXT: store i32
+; RESULT-NEXT: ret
+define void @no_sink_alloca() {
+ %alloca = alloca i32
+ call void @func()
+ store i32 0, ptr %alloca
+ ret void
+}
+
+; CHECK-LABEL: define i32 @cannot_sink_callbr(
+; CHECK: callbr i32
+
+; RESULT: store i32 1
+; RESULT-NEXT: ret i32 %load0
+
+; RESULT: store i32 2
+; RESULT-NEXT: ret i32 2
+
+; RESULT: store i32 3
+; RESULT-NEXT: ret i32 3
+define i32 @cannot_sink_callbr(ptr %arg0, ptr %ptr1) {
+entry:
+ %load0 = load i32, ptr %arg0
+ %callbr = callbr i32 asm "", "=r,r,!i,!i"(i32 %load0)
+ to label %one [label %two, label %three]
+one:
+ store i32 1, ptr %ptr1
+ ret i32 %load0
+
+two:
+ store i32 2, ptr %ptr1
+ ret i32 2
+
+three:
+ store i32 3, ptr %ptr1
+ ret i32 3
+}
+
+declare i32 @__gxx_personality_v0(...)
+declare i32 @maybe_throwing_callee(i32)
+declare void @did_not_throw(i32)
+
+; landingpad must be first in the block, so it cannot be sunk.
+; CHECK-LABEL: @cannot_sink_landingpad(
+; INTERESTING: landingpad
+
+; RESULT: %landing = landingpad { ptr, i32 }
+; RESULT-NEXT: catch ptr
+; RESULT-NEXT: call void @func(
+; RESULT-NEXT: call void @func(
+; RESULT-NEXT: extractvalue { ptr, i32 } %landing, 1
+define void @cannot_sink_landingpad(i32 %arg) personality ptr @__gxx_personality_v0 {
+bb:
+ %i0 = invoke i32 @maybe_throwing_callee(i32 %arg)
+ to label %bb3 unwind label %bb1
+
+bb1: ; preds = %bb
+ %landing = landingpad { ptr, i32 }
+ catch ptr null
+ call void @func()
+ call void @func()
+ %extract0 = extractvalue { ptr, i32 } %landing, 1
+ call void @use(i32 %extract0)
+ br label %bb4
+
+bb3: ; preds = %bb
+ call void @did_not_throw(i32 %i0)
+ br label %bb4
+
+bb4: ; preds = %bb3, %bb1
+ ret void
+}
+
+; CHECK-LABEL: define void @sink_multiple_uses() {
+; INTERESTING: call i32 @leaf(
+; INTERESTING: call void @use0(
+
+; RESULT-NEXT: call void @func(
+; RESULT-NEXT: %ret = call i32 @leaf()
+; RESULT-NEXT: call void @use0(i32 %ret)
+define void @sink_multiple_uses() {
+ %ret = call i32 @leaf()
+ call void @func()
+ call void @use0(i32 %ret)
+ call void @func()
+ call void @use1(i32 %ret)
+ call void @func()
+ call void @use2(i32 %ret)
+ ret void
+}
+
+; CHECK-LABEL: define i32 @can_sink_end_diamond(
+; RESULT: entry:
+; RESULT-NEXT: br i1
+
+; RESULT: endif:
+; RESULT-NEXT: %val = call i32 @leaf()
+; RESULT-NEXT: call void @use(i32 %val)
+; RESULT-NEXT: ret i32 %val
+define i32 @can_sink_end_diamond(i1 %cond) {
+entry:
+ %val = call i32 @leaf()
+ br i1 %cond, label %a, label %b
+
+a:
+ br label %endif
+
+b:
+ br label %endif
+
+endif:
+ call void @use(i32 %val)
+ ret i32 %val
+}
+
+; CHECK-LABEL: define i32 @cannot_sink_diamond_end_0(
+; RESULT: entry:
+; RESULT-NEXT: %val = call i32 @leaf()
+define i32 @cannot_sink_diamond_end_0(i1 %cond) {
+entry:
+ %val = call i32 @leaf()
+ br i1 %cond, label %a, label %b
+
+a:
+ call void @use0(i32 %val)
+ br label %endif
+
+b:
+ call void @use1(i32 %val)
+ br label %endif
+
+endif:
+ ret i32 %val
+}
+
+; CHECK-LABEL: define void @cannot_sink_diamond_end_1(
+; RESULT: entry:
+; RESULT-NEXT: %val = call i32 @leaf()
+define void @cannot_sink_diamond_end_1(i1 %cond) {
+entry:
+ %val = call i32 @leaf()
+ br i1 %cond, label %a, label %b
+
+a:
+ call void @use0(i32 %val)
+ br label %endif
+
+b:
+ call void @use1(i32 %val)
+ br label %endif
+
+endif:
+ ret void
+}
diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt
index c8673b42bee74..cf6701a3f0d5f 100644
--- a/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -60,6 +60,7 @@ add_llvm_tool(llvm-reduce
deltas/ReduceRegisterMasks.cpp
deltas/ReduceRegisterDefs.cpp
deltas/ReduceRegisterUses.cpp
+ deltas/ReduceSinkDefsToUses.cpp
deltas/ReduceTargetFeaturesAttr.cpp
deltas/ReduceUsingSimplifyCFG.cpp
deltas/RunIRPasses.cpp
diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp
index 9b13202f9fec4..769e8a0730138 100644
--- a/llvm/tools/llvm-reduce/DeltaManager.cpp
+++ b/llvm/tools/llvm-reduce/DeltaManager.cpp
@@ -45,6 +45,7 @@
#include "deltas/ReduceRegisterDefs.h"
#include "deltas/ReduceRegisterMasks.h"
#include "deltas/ReduceRegisterUses.h"
+#include "deltas/ReduceSinkDefsToUses.h"
#include "deltas/ReduceSpecialGlobals.h"
#include "deltas/ReduceTargetFeaturesAttr.h"
#include "deltas/ReduceUsingSimplifyCFG.h"
diff --git a/llvm/tools/llvm-reduce/DeltaPasses.def b/llvm/tools/llvm-reduce/DeltaPasses.def
index 845b1061592ef..1ec73544343e0 100644
--- a/llvm/tools/llvm-reduce/DeltaPasses.def
+++ b/llvm/tools/llvm-reduce/DeltaPasses.def
@@ -59,6 +59,7 @@ DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic
DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes")
DELTA_PASS_IR("instruction-flags", reduceInstructionFlagsDeltaPass, "Reducing Instruction Flags")
DELTA_PASS_IR("inline-call-sites", reduceInlineCallSitesDeltaPass, "Inlining callsites")
+DELTA_PASS_IR("sink-defs-to-uses", reduceSinkDefsToUsesDeltaPass, "Sinking defs to uses")
#ifndef DELTA_PASS_MIR
#define DELTA_PASS_MIR(NAME, FUNC, DESC)
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp
new file mode 100644
index 0000000000000..454a6e4c4e7d0
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.cpp
@@ -0,0 +1,61 @@
+//===- ReduceSinkDefsToUses.cpp - Specialized Delta Pass ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Try to move defs to be next to their uses
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceSinkDefsToUses.h"
+#include "Utils.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+
+using namespace llvm;
+
+static bool shouldPreserveUsePosition(const Instruction &I) {
+ return isa<AllocaInst>(I) || isa<PHINode>(I) || I.isEHPad();
+}
+
+static bool shouldPreserveDefPosition(const Instruction &I) {
+ return shouldPreserveUsePosition(I) || I.isTerminator();
+}
+
+static void sinkDefsToUsesInFunction(Oracle &O, Function &F) {
+ DominatorTree DT(F);
+
+ for (BasicBlock &BB : F) {
+ for (Instruction &UseInst : make_early_inc_range(reverse(BB))) {
+ if (shouldPreserveUsePosition(UseInst))
+ continue;
+
+ for (Value *UseOp : UseInst.operands()) {
+ Instruction *DefInst = dyn_cast<Instruction>(UseOp);
+ if (!DefInst || shouldPreserveDefPosition(*DefInst))
+ continue;
+
+ if (!all_of(DefInst->users(), [&](const User *DefUser) {
+ return DefUser == &UseInst ||
+ DT.dominates(&UseInst, cast<Instruction>(DefUser));
+ })) {
+ continue;
+ }
+
+ if (!O.shouldKeep())
+ DefInst->moveBeforePreserving(UseInst.getIterator());
+ }
+ }
+ }
+}
+
+void llvm::reduceSinkDefsToUsesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {
+ Module &M = WorkItem.getModule();
+ for (Function &F : M) {
+ if (!F.isDeclaration())
+ sinkDefsToUsesInFunction(O, F);
+ }
+}
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h
new file mode 100644
index 0000000000000..422d0ea2ded80
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceSinkDefsToUses.h
@@ -0,0 +1,18 @@
+//===- ReduceSinkDefsToUses.h - Specialized Delta Pass ----------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_SINKDEFSTOUSES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_SINKDEFSTOUSES_H
+
+#include "Delta.h"
+
+namespace llvm {
+void reduceSinkDefsToUsesDeltaPass(Oracle &O, ReducerWorkItem &WorkItem);
+} // namespace llvm
+
+#endif
diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
index 0c7affba2b4c5..5d5d9f0dbd840 100644
--- a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
@@ -48,6 +48,7 @@ executable("llvm-reduce") {
"deltas/ReduceRegisterDefs.cpp",
"deltas/ReduceRegisterMasks.cpp",
"deltas/ReduceRegisterUses.cpp",
+ "deltas/ReduceSinkDefsToUses.cpp",
"deltas/ReduceSpecialGlobals.cpp",
"deltas/ReduceTargetFeaturesAttr.cpp",
"deltas/ReduceUsingSimplifyCFG.cpp",
More information about the llvm-commits
mailing list