Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MacroFusion] Support multiple predicators #72219

Merged
merged 3 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions llvm/include/llvm/CodeGen/MacroFusion.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#ifndef LLVM_CODEGEN_MACROFUSION_H
#define LLVM_CODEGEN_MACROFUSION_H

#include <functional>
#include "llvm/ADT/ArrayRef.h"
#include <memory>

namespace llvm {
Expand All @@ -29,10 +29,10 @@ class SUnit;
/// Check if the instr pair, FirstMI and SecondMI, should be fused
/// together. Given SecondMI, when FirstMI is unspecified, then check if
/// SecondMI may be part of a fused pair at all.
using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII,
const TargetSubtargetInfo &TSI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI)>;
using MacroFusionPredTy = bool (*)(const TargetInstrInfo &TII,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function_ref?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this can't be done as it causes some compilation failures due to incompatible type with single element ArrayRef.

const TargetSubtargetInfo &STI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI);

/// Checks if the number of cluster edges between SU and its predecessors is
/// less than FuseLimit
Expand All @@ -48,15 +48,17 @@ bool fuseInstructionPair(ScheduleDAGInstrs &DAG, SUnit &FirstSU,

/// Create a DAG scheduling mutation to pair instructions back to back
/// for instructions that benefit according to the target-specific
/// shouldScheduleAdjacent predicate function.
/// predicate functions. shouldScheduleAdjacent will be true if any of the
/// provided predicates are true.
std::unique_ptr<ScheduleDAGMutation>
createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
createMacroFusionDAGMutation(ArrayRef<MacroFusionPredTy> Predicates);

/// Create a DAG scheduling mutation to pair branch instructions with one
/// of their predecessors back to back for instructions that benefit according
/// to the target-specific shouldScheduleAdjacent predicate function.
/// to the target-specific predicate functions. shouldScheduleAdjacent will be
/// true if any of the provided predicates are true.
std::unique_ptr<ScheduleDAGMutation>
createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
createBranchMacroFusionDAGMutation(ArrayRef<MacroFusionPredTy> Predicates);

} // end namespace llvm

Expand Down
37 changes: 25 additions & 12 deletions llvm/lib/CodeGen/MacroFusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,34 @@ namespace {
/// Post-process the DAG to create cluster edges between instrs that may
/// be fused by the processor into a single operation.
class MacroFusion : public ScheduleDAGMutation {
ShouldSchedulePredTy shouldScheduleAdjacent;
std::vector<MacroFusionPredTy> Predicates;
bool FuseBlock;
bool scheduleAdjacentImpl(ScheduleDAGInstrs &DAG, SUnit &AnchorSU);

public:
MacroFusion(ShouldSchedulePredTy shouldScheduleAdjacent, bool FuseBlock)
: shouldScheduleAdjacent(shouldScheduleAdjacent), FuseBlock(FuseBlock) {}
MacroFusion(ArrayRef<MacroFusionPredTy> Predicates, bool FuseBlock)
: Predicates(Predicates.begin(), Predicates.end()), FuseBlock(FuseBlock) {
}

void apply(ScheduleDAGInstrs *DAGInstrs) override;

bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
const TargetSubtargetInfo &STI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI);
};

} // end anonymous namespace

bool MacroFusion::shouldScheduleAdjacent(const TargetInstrInfo &TII,
const TargetSubtargetInfo &STI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI) {
return llvm::any_of(Predicates, [&](MacroFusionPredTy Predicate) {
return Predicate(TII, STI, FirstMI, SecondMI);
});
}

void MacroFusion::apply(ScheduleDAGInstrs *DAG) {
if (FuseBlock)
// For each of the SUnits in the scheduling block, try to fuse the instr in
Expand Down Expand Up @@ -197,17 +212,15 @@ bool MacroFusion::scheduleAdjacentImpl(ScheduleDAGInstrs &DAG, SUnit &AnchorSU)
}

std::unique_ptr<ScheduleDAGMutation>
llvm::createMacroFusionDAGMutation(
ShouldSchedulePredTy shouldScheduleAdjacent) {
if(EnableMacroFusion)
return std::make_unique<MacroFusion>(shouldScheduleAdjacent, true);
llvm::createMacroFusionDAGMutation(ArrayRef<MacroFusionPredTy> Predicates) {
if (EnableMacroFusion)
return std::make_unique<MacroFusion>(Predicates, true);
return nullptr;
}

std::unique_ptr<ScheduleDAGMutation>
llvm::createBranchMacroFusionDAGMutation(
ShouldSchedulePredTy shouldScheduleAdjacent) {
if(EnableMacroFusion)
return std::make_unique<MacroFusion>(shouldScheduleAdjacent, false);
std::unique_ptr<ScheduleDAGMutation> llvm::createBranchMacroFusionDAGMutation(
ArrayRef<MacroFusionPredTy> Predicates) {
if (EnableMacroFusion)
return std::make_unique<MacroFusion>(Predicates, false);
return nullptr;
}
4 changes: 2 additions & 2 deletions llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ namespace {
/// be turned into VOPD instructions
/// Greedily pairs instruction candidates. O(n^2) algorithm.
struct VOPDPairingMutation : ScheduleDAGMutation {
ShouldSchedulePredTy shouldScheduleAdjacent; // NOLINT: function pointer
MacroFusionPredTy shouldScheduleAdjacent; // NOLINT: function pointer

VOPDPairingMutation(
ShouldSchedulePredTy shouldScheduleAdjacent) // NOLINT: function pointer
MacroFusionPredTy shouldScheduleAdjacent) // NOLINT: function pointer
: shouldScheduleAdjacent(shouldScheduleAdjacent) {}

void apply(ScheduleDAGInstrs *DAG) override {
Expand Down