1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[GISel]: Provide standard interface to observe changes in GISel passes

https://reviews.llvm.org/D54980

This provides a standard API across GISel passes to observe and notify
passes about changes (insertions/deletions/mutations) to MachineInstrs.
This patch also removes the recordInsertion method in MachineIRBuilder
and instead provides method to setObserver.

Reviewed by: vkeles.

llvm-svn: 348406
This commit is contained in:
Aditya Nandakumar 2018-12-05 20:14:52 +00:00
parent 76ec777049
commit ba54e27cac
22 changed files with 214 additions and 115 deletions

View File

@ -24,16 +24,6 @@ class CombinerInfo;
class TargetPassConfig;
class MachineFunction;
class CombinerChangeObserver {
public:
virtual ~CombinerChangeObserver() {}
/// An instruction was erased.
virtual void erasedInstr(MachineInstr &MI) = 0;
/// An instruction was created and inseerted into the function.
virtual void createdInstr(MachineInstr &MI) = 0;
};
class Combiner {
public:
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC);

View File

@ -20,7 +20,7 @@
namespace llvm {
class CombinerChangeObserver;
class GISelChangeObserver;
class MachineIRBuilder;
class MachineRegisterInfo;
class MachineInstr;
@ -28,13 +28,13 @@ class MachineInstr;
class CombinerHelper {
MachineIRBuilder &Builder;
MachineRegisterInfo &MRI;
CombinerChangeObserver &Observer;
GISelChangeObserver &Observer;
void eraseInstr(MachineInstr &MI);
void scheduleForVisit(MachineInstr &MI);
public:
CombinerHelper(CombinerChangeObserver &Observer, MachineIRBuilder &B);
CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B);
/// If \p MI is COPY, try to combine it.
/// Returns true if MI changed.

View File

@ -17,7 +17,7 @@
#include <cassert>
namespace llvm {
class CombinerChangeObserver;
class GISelChangeObserver;
class LegalizerInfo;
class MachineInstr;
class MachineIRBuilder;
@ -43,7 +43,7 @@ public:
/// illegal ops that are created.
bool LegalizeIllegalOps; // TODO: Make use of this.
const LegalizerInfo *LInfo;
virtual bool combine(CombinerChangeObserver &Observer, MachineInstr &MI,
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
MachineIRBuilder &B) const = 0;
};
} // namespace llvm

View File

@ -0,0 +1,38 @@
//== ----- llvm/CodeGen/GlobalISel/GISelChangeObserver.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 allow clients to notify changes to machine
/// instr.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
namespace llvm {
/// Abstract class that contains various methods for clients to notify about
/// changes. This should be the preferred way for APIs to notify changes.
/// Typically calling erasedInstr/createdInstr multiple times should not affect
/// the result. The observer would likely need to check if it was already
/// notified earlier (consider using GISelWorkList).
class MachineInstr;
class GISelChangeObserver {
public:
virtual ~GISelChangeObserver() {}
/// An instruction was erased.
virtual void erasedInstr(MachineInstr &MI) = 0;
/// An instruction was created and inserted into the function.
virtual void createdInstr(MachineInstr &MI) = 0;
/// This instruction was mutated in some way.
virtual void changedInstr(MachineInstr &MI) = 0;
};
} // namespace llvm
#endif

View File

@ -32,6 +32,7 @@ namespace llvm {
class LegalizerInfo;
class Legalizer;
class MachineRegisterInfo;
class GISelChangeObserver;
class LegalizerHelper {
public:
@ -48,8 +49,9 @@ public:
UnableToLegalize,
};
LegalizerHelper(MachineFunction &MF);
LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI);
LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer);
LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
GISelChangeObserver &Observer);
/// Replace \p MI by a sequence of legal instructions that can implement the
/// same operation. Note that this means \p MI may be deleted, so any iterator
@ -117,6 +119,8 @@ private:
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;
/// To keep track of changes made by the LegalizerHelper.
GISelChangeObserver &Observer;
};
/// Helper function that creates the given libcall.

View File

@ -39,6 +39,7 @@ class MachineInstr;
class MachineIRBuilder;
class MachineRegisterInfo;
class MCInstrInfo;
class GISelChangeObserver;
namespace LegalizeActions {
enum LegalizeAction : std::uint8_t {
@ -949,9 +950,9 @@ public:
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
virtual bool legalizeCustom(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const;
virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const;
private:
/// Determine what action should be taken to legalize the given generic

View File

@ -30,6 +30,7 @@ namespace llvm {
class MachineFunction;
class MachineInstr;
class TargetInstrInfo;
class GISelChangeObserver;
/// Class which stores all the state required in a MachineIRBuilder.
/// Since MachineIRBuilders will only store state in this object, it allows
@ -50,7 +51,7 @@ struct MachineIRBuilderState {
MachineBasicBlock::iterator II;
/// @}
std::function<void(MachineInstr *)> InsertedInstr;
GISelChangeObserver *Observer;
};
/// Helper class to build MachineInstr.
@ -61,6 +62,7 @@ class MachineIRBuilderBase {
MachineIRBuilderState State;
void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
void recordInsertion(MachineInstr *MI) const;
protected:
unsigned getDestFromArg(unsigned Reg) { return Reg; }
@ -151,12 +153,8 @@ public:
void setInstr(MachineInstr &MI);
/// @}
/// \name Control where instructions we create are recorded (typically for
/// visiting again later during legalization).
/// @{
void recordInsertion(MachineInstr *InsertedInstr) const;
void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
void stopRecordingInsertions();
void setChangeObserver(GISelChangeObserver &Observer);
void stopObservingChanges();
/// @}
/// Set the debug location to \p DL for all the next build instructions.

View File

@ -12,12 +12,13 @@
//===----------------------------------------------------------------------===//
#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/CombinerInfo.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
@ -34,7 +35,7 @@ namespace {
/// instruction creation will schedule that instruction for a future visit.
/// Other Combiner implementations may require more complex behaviour from
/// their CombinerChangeObserver subclass.
class WorkListMaintainer : public CombinerChangeObserver {
class WorkListMaintainer : public GISelChangeObserver {
using WorkListTy = GISelWorkList<512>;
WorkListTy &WorkList;
@ -50,6 +51,11 @@ public:
LLVM_DEBUG(dbgs() << "Created: "; MI.print(dbgs()); dbgs() << "\n");
WorkList.insert(&MI);
}
// Currently changed conservatively assumes erased.
void changedInstr(MachineInstr &MI) override {
LLVM_DEBUG(dbgs() << "Changed: "; MI.print(dbgs()); dbgs() << "\n");
WorkList.remove(&MI);
}
};
}

View File

@ -6,8 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GlobalISel/Combiner.h"
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
#include "llvm/CodeGen/GlobalISel/Combiner.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineInstr.h"
@ -18,7 +19,7 @@
using namespace llvm;
CombinerHelper::CombinerHelper(CombinerChangeObserver &Observer,
CombinerHelper::CombinerHelper(GISelChangeObserver &Observer,
MachineIRBuilder &B)
: Builder(B), MRI(Builder.getMF().getRegInfo()), Observer(Observer) {}

View File

@ -16,6 +16,7 @@
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
@ -67,6 +68,42 @@ static bool isArtifact(const MachineInstr &MI) {
return true;
}
}
using InstListTy = GISelWorkList<256>;
using ArtifactListTy = GISelWorkList<128>;
class LegalizerWorkListManager : public GISelChangeObserver {
InstListTy &InstList;
ArtifactListTy &ArtifactList;
public:
LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
: InstList(Insts), ArtifactList(Arts) {}
void createdInstr(MachineInstr &MI) override {
// Only legalize pre-isel generic instructions.
// Legalization process could generate Target specific pseudo
// instructions with generic types. Don't record them
if (isPreISelGenericOpcode(MI.getOpcode())) {
if (isArtifact(MI))
ArtifactList.insert(&MI);
else
InstList.insert(&MI);
}
LLVM_DEBUG(dbgs() << ".. .. New MI: " << MI;);
}
void erasedInstr(MachineInstr &MI) override {
InstList.remove(&MI);
ArtifactList.remove(&MI);
}
void changedInstr(MachineInstr &MI) override {
// When insts change, we want to revisit them to legalize them again.
// We'll consider them the same as created.
LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI;);
createdInstr(MI);
}
};
bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
// If the ISel pipeline failed, do not bother running that pass.
@ -77,14 +114,13 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
init(MF);
const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
LegalizerHelper Helper(MF);
const size_t NumBlocks = MF.size();
MachineRegisterInfo &MRI = MF.getRegInfo();
// Populate Insts
GISelWorkList<256> InstList;
GISelWorkList<128> ArtifactList;
InstListTy InstList;
ArtifactListTy ArtifactList;
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
// Perform legalization bottom up so we can DCE as we legalize.
// Traverse BB in RPOT and within each basic block, add insts top down,
@ -103,24 +139,12 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
InstList.insert(&MI);
}
}
Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
// Only legalize pre-isel generic instructions.
// Legalization process could generate Target specific pseudo
// instructions with generic types. Don't record them
if (isPreISelGenericOpcode(MI->getOpcode())) {
if (isArtifact(*MI))
ArtifactList.insert(MI);
else
InstList.insert(MI);
}
LLVM_DEBUG(dbgs() << ".. .. New MI: " << *MI;);
});
LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
LegalizerHelper Helper(MF, WorkListObserver);
const LegalizerInfo &LInfo(Helper.getLegalizerInfo());
LegalizationArtifactCombiner ArtCombiner(Helper.MIRBuilder, MF.getRegInfo(), LInfo);
auto RemoveDeadInstFromLists = [&InstList,
&ArtifactList](MachineInstr *DeadMI) {
InstList.remove(DeadMI);
ArtifactList.remove(DeadMI);
auto RemoveDeadInstFromLists = [&WorkListObserver](MachineInstr *DeadMI) {
WorkListObserver.erasedInstr(*DeadMI);
};
bool Changed = false;
do {
@ -138,7 +162,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
// Error out if we couldn't legalize this instruction. We may want to
// fall back to DAG ISel instead in the future.
if (Res == LegalizerHelper::UnableToLegalize) {
Helper.MIRBuilder.stopRecordingInsertions();
Helper.MIRBuilder.stopObservingChanges();
reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
"unable to legalize instruction", MI);
return false;

View File

@ -15,6 +15,7 @@
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@ -29,14 +30,19 @@
using namespace llvm;
using namespace LegalizeActions;
LegalizerHelper::LegalizerHelper(MachineFunction &MF)
: MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
LegalizerHelper::LegalizerHelper(MachineFunction &MF,
GISelChangeObserver &Observer)
: MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()),
Observer(Observer) {
MIRBuilder.setMF(MF);
MIRBuilder.setChangeObserver(Observer);
}
LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI)
: MRI(MF.getRegInfo()), LI(LI) {
LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
GISelChangeObserver &Observer)
: MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
MIRBuilder.setMF(MF);
MIRBuilder.setChangeObserver(Observer);
}
LegalizerHelper::LegalizeResult
LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
@ -64,8 +70,8 @@ LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
case Custom:
LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
: UnableToLegalize;
return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
: UnableToLegalize;
default:
LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
return UnableToLegalize;
@ -682,7 +688,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
// Make the original instruction a trunc now, and update its source.
MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
@ -698,7 +704,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_SHL:
@ -707,7 +713,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
// unsigned integer:
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_SDIV:
@ -715,7 +721,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_ASHR:
@ -724,7 +730,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
// unsigned integer:
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_UDIV:
@ -733,7 +739,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_SELECT:
@ -745,7 +751,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_FPTOSI:
@ -753,21 +759,21 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
if (TypeIdx != 0)
return UnableToLegalize;
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_SITOFP:
if (TypeIdx != 1)
return UnableToLegalize;
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_UITOFP:
if (TypeIdx != 1)
return UnableToLegalize;
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_INSERT:
@ -775,7 +781,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
return UnableToLegalize;
widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_LOAD:
@ -789,7 +795,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
case TargetOpcode::G_SEXTLOAD:
case TargetOpcode::G_ZEXTLOAD:
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_STORE: {
@ -798,7 +804,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
return UnableToLegalize;
widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_CONSTANT: {
@ -808,7 +814,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
SrcMO.setCImm(ConstantInt::get(Ctx, Val));
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_FCONSTANT: {
@ -829,12 +835,12 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_BRCOND:
widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_FCMP:
@ -844,7 +850,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
}
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_ICMP:
@ -858,13 +864,13 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
widenScalarSrc(MI, WideTy, 2, ExtOpcode);
widenScalarSrc(MI, WideTy, 3, ExtOpcode);
}
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_GEP:
assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
case TargetOpcode::G_PHI: {
@ -879,14 +885,14 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
MachineBasicBlock &MBB = *MI.getParent();
MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
widenScalarDst(MI, WideTy);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_EXTRACT_VECTOR_ELT:
if (TypeIdx != 2)
return UnableToLegalize;
widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
}
@ -1122,7 +1128,7 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
// This trivially expands to CTLZ.
MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_CTLZ: {
@ -1170,7 +1176,7 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
// This trivially expands to CTTZ.
MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
MIRBuilder.recordInsertion(&MI);
Observer.changedInstr(MI);
return Legalized;
}
case TargetOpcode::G_CTTZ: {

View File

@ -19,6 +19,7 @@
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@ -375,7 +376,8 @@ bool LegalizerInfo::isLegal(const MachineInstr &MI,
}
bool LegalizerInfo::legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const {
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const {
return false;
}

View File

@ -10,6 +10,7 @@
/// This file implements the MachineIRBuidler class.
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
@ -29,7 +30,7 @@ void MachineIRBuilderBase::setMF(MachineFunction &MF) {
State.TII = MF.getSubtarget().getInstrInfo();
State.DL = DebugLoc();
State.II = MachineBasicBlock::iterator();
State.InsertedInstr = nullptr;
State.Observer = nullptr;
}
void MachineIRBuilderBase::setMBB(MachineBasicBlock &MBB) {
@ -54,18 +55,15 @@ void MachineIRBuilderBase::setInsertPt(MachineBasicBlock &MBB,
}
void MachineIRBuilderBase::recordInsertion(MachineInstr *InsertedInstr) const {
if (State.InsertedInstr)
State.InsertedInstr(InsertedInstr);
if (State.Observer)
State.Observer->createdInstr(*InsertedInstr);
}
void MachineIRBuilderBase::recordInsertions(
std::function<void(MachineInstr *)> Inserted) {
State.InsertedInstr = std::move(Inserted);
void MachineIRBuilderBase::setChangeObserver(GISelChangeObserver &Observer) {
State.Observer = &Observer;
}
void MachineIRBuilderBase::stopRecordingInsertions() {
State.InsertedInstr = nullptr;
}
void MachineIRBuilderBase::stopObservingChanges() { State.Observer = nullptr; }
//------------------------------------------------------------------------------
// Build instruction variants.

View File

@ -404,7 +404,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
bool AArch64LegalizerInfo::legalizeCustom(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const {
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const {
switch (MI.getOpcode()) {
default:
// No idea what to do.

View File

@ -15,6 +15,7 @@
#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H
#define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
namespace llvm {
@ -28,7 +29,8 @@ public:
AArch64LegalizerInfo(const AArch64Subtarget &ST);
bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const override;
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const override;
private:
bool legalizeVaArg(MachineInstr &MI, MachineRegisterInfo &MRI,

View File

@ -32,11 +32,11 @@ public:
AArch64PreLegalizerCombinerInfo()
: CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
/*LegalizerInfo*/ nullptr) {}
virtual bool combine(CombinerChangeObserver &Observer, MachineInstr &MI,
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
MachineIRBuilder &B) const override;
};
bool AArch64PreLegalizerCombinerInfo::combine(CombinerChangeObserver &Observer,
bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
MachineInstr &MI,
MachineIRBuilder &B) const {
CombinerHelper Helper(Observer, B);

View File

@ -318,7 +318,8 @@ ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const {
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const {
using namespace TargetOpcode;
MIRBuilder.setInstr(MI);

View File

@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_ARM_ARMMACHINELEGALIZER_H
#include "llvm/ADT/IndexedMap.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/IR/Instructions.h"
@ -29,7 +30,8 @@ public:
ARMLegalizerInfo(const ARMSubtarget &ST);
bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const override;
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const override;
private:
void setFCmpLibcallsGNU();

View File

@ -58,7 +58,8 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const {
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const {
using namespace TargetOpcode;

View File

@ -14,6 +14,7 @@
#ifndef LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H
#define LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
namespace llvm {
@ -26,7 +27,8 @@ public:
MipsLegalizerInfo(const MipsSubtarget &ST);
bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const override;
MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const override;
};
} // end namespace llvm
#endif

View File

@ -11,6 +11,13 @@
namespace {
class DummyGISelObserver : public GISelChangeObserver {
public:
void changedInstr(MachineInstr &MI) override {}
void createdInstr(MachineInstr &MI) override {}
void erasedInstr(MachineInstr &MI) override {}
};
// Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
// in which case it becomes CTTZ_ZERO_UNDEF with select.
TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ0) {
@ -23,7 +30,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ0) {
// Build Instr
auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
// Perform Legalization
ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -51,7 +59,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ1) {
// Build Instr
auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
// Perform Legalization
ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -81,7 +90,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ2) {
// Build
auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -109,7 +119,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ3) {
auto MIBCTTZ =
B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -132,7 +143,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ0) {
// Build
auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -159,7 +171,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTLZLibcall) {
// Build
auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, LLT::scalar(64), Copies[0]);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -189,7 +202,8 @@ TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ1) {
auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -228,7 +242,8 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTLZ) {
auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -260,7 +275,8 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTLZZeroUndef) {
auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
auto MIBCTLZ_ZU = B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -292,7 +308,8 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTPOP) {
auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBCTPOP, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -323,7 +340,8 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ_ZERO_UNDEF) {
auto MIBCTTZ_ZERO_UNDEF =
B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -353,7 +371,8 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ) {
auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, s8, MIBTrunc);
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -388,7 +407,8 @@ TEST_F(LegalizerHelperTest, WidenUADDO) {
.addUse(MIBTrunc->getOperand(0).getReg())
.addUse(MIBTrunc->getOperand(0).getReg());
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);
@ -426,7 +446,8 @@ TEST_F(LegalizerHelperTest, WidenUSUBO) {
.addUse(MIBTrunc->getOperand(0).getReg())
.addUse(MIBTrunc->getOperand(0).getReg());
AInfo Info(MF->getSubtarget());
LegalizerHelper Helper(*MF, Info);
DummyGISelObserver Observer;
LegalizerHelper Helper(*MF, Info, Observer);
ASSERT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
LegalizerHelper::LegalizeResult::Legalized);

View File

@ -8,6 +8,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"