Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Recommit rL305677: [CodeGen] Add generic MacroFusion pass
Use llvm::make_unique to avoid ambiguity with MSVC. This patch adds a generic MacroFusion pass, that is used on X86 and AArch64, which both define target-specific shouldScheduleAdjacent functions. This generic pass should make it easier for other targets to implement macro fusion and I intend to add macro fusion for ARM shortly. Differential Revision: https://reviews.llvm.org/D34144 llvm-svn: 305690
- Loading branch information
Showing
7 changed files
with
245 additions
and
253 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
//===- MacroFusion.h - Macro Fusion ------------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
/// \file This file contains the definition of the DAG scheduling mutation to | ||
/// pair instructions back to back. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <functional> | ||
#include "llvm/Target/TargetInstrInfo.h" | ||
#include "llvm/CodeGen/MachineScheduler.h" | ||
|
||
namespace llvm { | ||
|
||
/// \brief 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. | ||
typedef std::function<bool(const TargetInstrInfo &TII, | ||
const TargetSubtargetInfo &TSI, | ||
const MachineInstr *FirstMI, | ||
const MachineInstr &SecondMI)> ShouldSchedulePredTy; | ||
|
||
/// \brief Create a DAG scheduling mutation to pair instructions back to back | ||
/// for instructions that benefit according to the target-specific | ||
/// shouldScheduleAdjacent predicate function. | ||
std::unique_ptr<ScheduleDAGMutation> | ||
createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent); | ||
|
||
/// \brief 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. | ||
std::unique_ptr<ScheduleDAGMutation> | ||
createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent); | ||
|
||
} // end namespace llvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
//===- MacroFusion.cpp - Macro Fusion ----------------------===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
/// \file This file contains the implementation of the DAG scheduling mutation | ||
/// to pair instructions back to back. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/CodeGen/MacroFusion.h" | ||
#include "llvm/ADT/Statistic.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/Target/TargetInstrInfo.h" | ||
|
||
#define DEBUG_TYPE "misched" | ||
|
||
STATISTIC(NumFused, "Number of instr pairs fused"); | ||
|
||
using namespace llvm; | ||
|
||
static cl::opt<bool> EnableMacroFusion("misched-fusion", cl::Hidden, | ||
cl::desc("Enable scheduling for macro fusion."), cl::init(true)); | ||
|
||
namespace { | ||
|
||
static void fuseInstructionPair(ScheduleDAGMI &DAG, SUnit &FirstSU, | ||
SUnit &SecondSU) { | ||
// Create a single weak edge between the adjacent instrs. The only effect is | ||
// to cause bottom-up scheduling to heavily prioritize the clustered instrs. | ||
DAG.addEdge(&SecondSU, SDep(&FirstSU, SDep::Cluster)); | ||
|
||
// Adjust the latency between the anchor instr and its | ||
// predecessors. | ||
for (SDep &IDep : SecondSU.Preds) | ||
if (IDep.getSUnit() == &FirstSU) | ||
IDep.setLatency(0); | ||
|
||
// Adjust the latency between the dependent instr and its | ||
// predecessors. | ||
for (SDep &IDep : FirstSU.Succs) | ||
if (IDep.getSUnit() == &SecondSU) | ||
IDep.setLatency(0); | ||
|
||
DEBUG(dbgs() << DAG.MF.getName() << "(): Macro fuse "; | ||
FirstSU.print(dbgs(), &DAG); dbgs() << " - "; | ||
SecondSU.print(dbgs(), &DAG); dbgs() << " / "; | ||
dbgs() << DAG.TII->getName(FirstSU.getInstr()->getOpcode()) << " - " << | ||
DAG.TII->getName(SecondSU.getInstr()->getOpcode()) << '\n'; ); | ||
|
||
if (&SecondSU != &DAG.ExitSU) | ||
// Make instructions dependent on FirstSU also dependent on SecondSU to | ||
// prevent them from being scheduled between FirstSU and and SecondSU. | ||
for (const SDep &SI : FirstSU.Succs) { | ||
if (SI.getSUnit() == &SecondSU) | ||
continue; | ||
DEBUG(dbgs() << " Copy Succ "; | ||
SI.getSUnit()->print(dbgs(), &DAG); dbgs() << '\n';); | ||
DAG.addEdge(SI.getSUnit(), SDep(&SecondSU, SDep::Artificial)); | ||
} | ||
|
||
++NumFused; | ||
} | ||
|
||
|
||
/// \brief 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; | ||
bool FuseBlock; | ||
bool scheduleAdjacentImpl(ScheduleDAGMI &DAG, SUnit &AnchorSU); | ||
|
||
public: | ||
MacroFusion(ShouldSchedulePredTy shouldScheduleAdjacent, bool FuseBlock) | ||
: shouldScheduleAdjacent(shouldScheduleAdjacent), FuseBlock(FuseBlock) {} | ||
|
||
void apply(ScheduleDAGInstrs *DAGInstrs) override; | ||
}; | ||
|
||
void MacroFusion::apply(ScheduleDAGInstrs *DAGInstrs) { | ||
ScheduleDAGMI *DAG = static_cast<ScheduleDAGMI*>(DAGInstrs); | ||
|
||
if (FuseBlock) | ||
// For each of the SUnits in the scheduling block, try to fuse the instr in | ||
// it with one in its predecessors. | ||
for (SUnit &ISU : DAG->SUnits) | ||
scheduleAdjacentImpl(*DAG, ISU); | ||
|
||
if (DAG->ExitSU.getInstr()) | ||
// Try to fuse the instr in the ExitSU with one in its predecessors. | ||
scheduleAdjacentImpl(*DAG, DAG->ExitSU); | ||
} | ||
|
||
/// \brief Implement the fusion of instr pairs in the scheduling DAG, | ||
/// anchored at the instr in AnchorSU.. | ||
bool MacroFusion::scheduleAdjacentImpl(ScheduleDAGMI &DAG, SUnit &AnchorSU) { | ||
const MachineInstr &AnchorMI = *AnchorSU.getInstr(); | ||
const TargetInstrInfo &TII = *DAG.TII; | ||
const TargetSubtargetInfo &ST = DAG.MF.getSubtarget(); | ||
|
||
// Check if the anchor instr may be fused. | ||
if (!shouldScheduleAdjacent(TII, ST, nullptr, AnchorMI)) | ||
return false; | ||
|
||
// Explorer for fusion candidates among the dependencies of the anchor instr. | ||
for (SDep &Dep : AnchorSU.Preds) { | ||
// Ignore dependencies that don't enforce ordering. | ||
if (Dep.getKind() == SDep::Anti || Dep.getKind() == SDep::Output || | ||
Dep.isWeak()) | ||
continue; | ||
|
||
SUnit &DepSU = *Dep.getSUnit(); | ||
if (DepSU.isBoundaryNode()) | ||
continue; | ||
|
||
const MachineInstr *DepMI = DepSU.getInstr(); | ||
if (!shouldScheduleAdjacent(TII, ST, DepMI, AnchorMI)) | ||
continue; | ||
|
||
fuseInstructionPair(DAG, DepSU, AnchorSU); | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
} // end anonymous namespace | ||
|
||
|
||
namespace llvm { | ||
|
||
std::unique_ptr<ScheduleDAGMutation> | ||
createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent) { | ||
if(EnableMacroFusion) | ||
return llvm::make_unique<MacroFusion>(shouldScheduleAdjacent, true); | ||
return nullptr; | ||
} | ||
|
||
std::unique_ptr<ScheduleDAGMutation> | ||
createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent) { | ||
if(EnableMacroFusion) | ||
return llvm::make_unique<MacroFusion>(shouldScheduleAdjacent, false); | ||
return nullptr; | ||
} | ||
|
||
} // end namespace llvm |
Oops, something went wrong.