mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[GISel]: Implement GlobalISel combiner API.
https://reviews.llvm.org/D41373 The various components are GICombinerHelper contains transformations that are common to all targets. Targets can pick and choose which transformations (at function/opcode granularity) each pass uses via configuring a GICombinerInfo. GICombiner contains some common code and it does the traversal, driving of combines, worklist management and iterating until convergence. GICombinerInfo is an interface with a virtual method called combine. The combiner info will allow targets to pick and choose (or implement their own specific combines). CombineInfos can make use of available combines in GICombineHelper to configure the transformations for a particular pass. Currently this approach allows cherry picking transformations from helpers (at function/opcode granularity) and also allows early returning on specific transformations. Targets also get to prioritize whether target specific combines run before/after the opt-in generic combines. Ideally we would like this part to be configured by both C++ and Tablegen. The CombinerInfo also has a field which indicates how to deal with IllegalOps (ie - should we allow to create them/or legalize them?). A CombinerPass would configure a CombinerInfo, create the GICombiner with the Info, and call GICombiner::combineMachineInstrs(MachineFunction&). This organization is very similar to the GISelLegalizer. llvm-svn: 323392
This commit is contained in:
parent
081998b7f1
commit
65202b9329
43
include/llvm/CodeGen/GlobalISel/Combiner.h
Normal file
43
include/llvm/CodeGen/GlobalISel/Combiner.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == //
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
/// This contains common code to drive combines. Combiner Passes will need to
|
||||||
|
/// setup a CombinerInfo and call combineMachineFunction.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H
|
||||||
|
#define LLVM_CODEGEN_GLOBALISEL_COMBINER_H
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class MachineRegisterInfo;
|
||||||
|
class CombinerInfo;
|
||||||
|
class TargetPassConfig;
|
||||||
|
class MachineFunction;
|
||||||
|
|
||||||
|
class Combiner {
|
||||||
|
public:
|
||||||
|
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC);
|
||||||
|
|
||||||
|
bool combineMachineInstrs(MachineFunction &MF);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CombinerInfo &CInfo;
|
||||||
|
|
||||||
|
MachineRegisterInfo *MRI = nullptr;
|
||||||
|
const TargetPassConfig *TPC;
|
||||||
|
MachineIRBuilder Builder;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace llvm.
|
||||||
|
|
||||||
|
#endif // LLVM_CODEGEN_GLOBALISEL_GICOMBINER_H
|
44
include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Normal file
44
include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//== llvm/CodeGen/GlobalISel/CombinerHelper.h -------------- -*- C++ -*-==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
/// This contains common combine transformations that may be used in a combine
|
||||||
|
/// pass,or by the target elsewhere.
|
||||||
|
/// Targets can pick individual opcode transformations from the helper or use
|
||||||
|
/// tryCombine which invokes all transformations. All of the transformations
|
||||||
|
/// return true if the MachineInstruction changed and false otherwise.
|
||||||
|
//
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
|
||||||
|
#define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class MachineIRBuilder;
|
||||||
|
class MachineRegisterInfo;
|
||||||
|
class MachineInstr;
|
||||||
|
|
||||||
|
class CombinerHelper {
|
||||||
|
MachineIRBuilder &Builder;
|
||||||
|
MachineRegisterInfo &MRI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CombinerHelper(MachineIRBuilder &B);
|
||||||
|
|
||||||
|
/// If \p MI is COPY, try to combine it.
|
||||||
|
/// Returns true if MI changed.
|
||||||
|
bool tryCombineCopy(MachineInstr &MI);
|
||||||
|
|
||||||
|
/// Try to transform \p MI by using all of the above
|
||||||
|
/// combine functions. Returns true if changed.
|
||||||
|
bool tryCombine(MachineInstr &MI);
|
||||||
|
};
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif
|
47
include/llvm/CodeGen/GlobalISel/CombinerInfo.h
Normal file
47
include/llvm/CodeGen/GlobalISel/CombinerInfo.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
/// Interface for Targets to specify which operations are combined how and when.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H
|
||||||
|
#define LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class LegalizerInfo;
|
||||||
|
class MachineInstr;
|
||||||
|
class MachineIRBuilder;
|
||||||
|
class MachineRegisterInfo;
|
||||||
|
// Contains information relevant to enabling/disabling various combines for a
|
||||||
|
// pass.
|
||||||
|
class CombinerInfo {
|
||||||
|
public:
|
||||||
|
CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal,
|
||||||
|
LegalizerInfo *LInfo)
|
||||||
|
: IllegalOpsAllowed(AllowIllegalOps),
|
||||||
|
LegalizeIllegalOps(ShouldLegalizeIllegal), LInfo(LInfo) {
|
||||||
|
assert(((AllowIllegalOps || !LegalizeIllegalOps) || LInfo) &&
|
||||||
|
"Expecting legalizerInfo when illegalops not allowed");
|
||||||
|
}
|
||||||
|
virtual ~CombinerInfo() = default;
|
||||||
|
/// If \p IllegalOpsAllowed is false, the CombinerHelper will make use of
|
||||||
|
/// the legalizerInfo to check for legality before each transformation.
|
||||||
|
bool IllegalOpsAllowed; // TODO: Make use of this.
|
||||||
|
|
||||||
|
/// If \p LegalizeIllegalOps is true, the Combiner will also legalize the
|
||||||
|
/// illegal ops that are created.
|
||||||
|
bool LegalizeIllegalOps; // TODO: Make use of this.
|
||||||
|
const LegalizerInfo *LInfo;
|
||||||
|
virtual bool combine(MachineInstr &MI, MachineIRBuilder &B) const = 0;
|
||||||
|
};
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
add_llvm_library(LLVMGlobalISel
|
add_llvm_library(LLVMGlobalISel
|
||||||
CallLowering.cpp
|
CallLowering.cpp
|
||||||
GlobalISel.cpp
|
GlobalISel.cpp
|
||||||
|
Combiner.cpp
|
||||||
|
CombinerHelper.cpp
|
||||||
IRTranslator.cpp
|
IRTranslator.cpp
|
||||||
InstructionSelect.cpp
|
InstructionSelect.cpp
|
||||||
InstructionSelector.cpp
|
InstructionSelector.cpp
|
||||||
|
81
lib/CodeGen/GlobalISel/Combiner.cpp
Normal file
81
lib/CodeGen/GlobalISel/Combiner.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
//===-- lib/CodeGen/GlobalISel/GICombiner.cpp -----------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file constains common code to combine machine functions at generic
|
||||||
|
// level.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/GlobalISel/Combiner.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||||
|
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
|
||||||
|
#include "llvm/ADT/PostOrderIterator.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
||||||
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "gi-combiner"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
Combiner::Combiner(CombinerInfo &Info, const TargetPassConfig *TPC)
|
||||||
|
: CInfo(Info), TPC(TPC) {
|
||||||
|
(void)this->TPC; // FIXME: Remove when used.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Combiner::combineMachineInstrs(MachineFunction &MF) {
|
||||||
|
// If the ISel pipeline failed, do not bother running this pass.
|
||||||
|
// FIXME: Should this be here or in individual combiner passes.
|
||||||
|
if (MF.getProperties().hasProperty(
|
||||||
|
MachineFunctionProperties::Property::FailedISel))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MRI = &MF.getRegInfo();
|
||||||
|
Builder.setMF(MF);
|
||||||
|
|
||||||
|
DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n');
|
||||||
|
|
||||||
|
MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
|
||||||
|
|
||||||
|
bool MFChanged = false;
|
||||||
|
bool Changed;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Collect all instructions. Do a post order traversal for basic blocks and
|
||||||
|
// insert with list bottom up, so while we pop_back_val, we'll traverse top
|
||||||
|
// down RPOT.
|
||||||
|
Changed = false;
|
||||||
|
GISelWorkList<512> WorkList;
|
||||||
|
for (MachineBasicBlock *MBB : post_order(&MF)) {
|
||||||
|
if (MBB->empty())
|
||||||
|
continue;
|
||||||
|
for (auto MII = MBB->rbegin(), MIE = MBB->rend(); MII != MIE;) {
|
||||||
|
MachineInstr *CurMI = &*MII;
|
||||||
|
++MII;
|
||||||
|
// Erase dead insts before even adding to the list.
|
||||||
|
if (isTriviallyDead(*CurMI, *MRI)) {
|
||||||
|
DEBUG(dbgs() << *CurMI << "Is dead; erasing.\n");
|
||||||
|
CurMI->eraseFromParentAndMarkDBGValuesForRemoval();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
WorkList.insert(CurMI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Main Loop. Process the instructions here.
|
||||||
|
while (!WorkList.empty()) {
|
||||||
|
MachineInstr *CurrInst = WorkList.pop_back_val();
|
||||||
|
DEBUG(dbgs() << "Try combining " << *CurrInst << "\n";);
|
||||||
|
Changed |= CInfo.combine(*CurrInst, Builder);
|
||||||
|
}
|
||||||
|
MFChanged |= Changed;
|
||||||
|
} while (Changed);
|
||||||
|
|
||||||
|
return MFChanged;
|
||||||
|
}
|
41
lib/CodeGen/GlobalISel/CombinerHelper.cpp
Normal file
41
lib/CodeGen/GlobalISel/CombinerHelper.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//== ---lib/CodeGen/GlobalISel/GICombinerHelper.cpp --------------------- == //
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "gi-combine"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
CombinerHelper::CombinerHelper(MachineIRBuilder &B) :
|
||||||
|
Builder(B), MRI(Builder.getMF().getRegInfo()) {}
|
||||||
|
|
||||||
|
bool CombinerHelper::tryCombineCopy(MachineInstr &MI) {
|
||||||
|
if (MI.getOpcode() != TargetOpcode::COPY)
|
||||||
|
return false;
|
||||||
|
unsigned DstReg = MI.getOperand(0).getReg();
|
||||||
|
unsigned SrcReg = MI.getOperand(1).getReg();
|
||||||
|
LLT DstTy = MRI.getType(DstReg);
|
||||||
|
LLT SrcTy = MRI.getType(SrcReg);
|
||||||
|
// Simple Copy Propagation.
|
||||||
|
// a(sx) = COPY b(sx) -> Replace all uses of a with b.
|
||||||
|
if (DstTy.isValid() && SrcTy.isValid() && DstTy == SrcTy) {
|
||||||
|
MI.eraseFromParent();
|
||||||
|
MRI.replaceRegWith(DstReg, SrcReg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CombinerHelper::tryCombine(MachineInstr &MI) {
|
||||||
|
return tryCombineCopy(MI);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user