Skip to content

Commit

Permalink
[globalisel][tablegen] Finish fixing compile-time regressions by merg…
Browse files Browse the repository at this point in the history
…ing the matcher and emitter state machines.

Summary:
Also, made a few minor tweaks to shave off a little more cumulative memory consumption:
* All rules share a single NewMIs instead of constructing their own. Only one
  will end up using it.
* Use MIs.resize(1) instead of MIs.clear();MIs.push_back(I) and prevent
  GIM_RecordInsn from changing MIs[0].

Depends on D33764

Reviewers: rovka, vitalybuka, ab, t.p.northover, qcolombet, aditya_nandakumar

Reviewed By: ab

Subscribers: kristof.beyls, igorb, llvm-commits

Differential Revision: https://reviews.llvm.org/D33766

llvm-svn: 307159
  • Loading branch information
dsandersllvm committed Jul 5, 2017
1 parent b78adec commit a6cfce6
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 477 deletions.
21 changes: 10 additions & 11 deletions llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ enum {
/// - OpIdx - Operand index
GIM_CheckIsMBB,

/// A successful match
GIM_Accept,
};
/// Check if the specified operand is safe to fold into the current
/// instruction.
/// - InsnID - Instruction ID
GIM_CheckIsSafeToFold,

//=== Renderers ===

enum {
/// Mutate an instruction
/// - NewInsnID - Instruction ID to define
/// - OldInsnID - Instruction ID to mutate
Expand Down Expand Up @@ -225,15 +227,12 @@ class InstructionSelector {
template <class TgtInstructionSelector, class PredicateBitset,
class ComplexMatcherMemFn>
bool executeMatchTable(
TgtInstructionSelector &ISel, MatcherState &State,
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
const int64_t *MatchTable, MachineRegisterInfo &MRI,
const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI,
const PredicateBitset &AvailableFeatures) const;
void executeEmitTable(NewMIVector &OutMIs, MatcherState &State,
const int64_t *EmitTable, const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const;

/// Constrain a register operand of an instruction \p I to a specified
/// register class. This could involve inserting COPYs before (for uses) or
Expand Down
165 changes: 157 additions & 8 deletions llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ namespace llvm {
template <class TgtInstructionSelector, class PredicateBitset,
class ComplexMatcherMemFn>
bool InstructionSelector::executeMatchTable(
TgtInstructionSelector &ISel, MatcherState &State,
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
const int64_t *MatchTable, MachineRegisterInfo &MRI,
const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI,
const PredicateBitset &AvailableFeatures) const {
const int64_t *Command = MatchTable;
while (true) {
Expand All @@ -33,6 +34,10 @@ bool InstructionSelector::executeMatchTable(
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;

// As an optimisation we require that MIs[0] is always the root. Refuse
// any attempt to modify it.
assert(NewInsnID != 0 && "Refusing to modify MIs[0]");

MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
if (!MO.isReg()) {
DEBUG(dbgs() << "Rejected (not a register)\n");
Expand Down Expand Up @@ -66,10 +71,12 @@ bool InstructionSelector::executeMatchTable(
case GIM_CheckOpcode: {
int64_t InsnID = *Command++;
int64_t Expected = *Command++;
DEBUG(dbgs() << "GIM_CheckOpcode(MIs[" << InsnID
<< "], ExpectedOpcode=" << Expected << ")\n");

unsigned Opcode = State.MIs[InsnID]->getOpcode();
DEBUG(dbgs() << "GIM_CheckOpcode(MIs[" << InsnID << "], ExpectedOpcode="
<< Expected << ") // Got=" << Opcode << "\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (State.MIs[InsnID]->getOpcode() != Expected)
if (Opcode != Expected)
return false;
break;
}
Expand Down Expand Up @@ -160,9 +167,151 @@ bool InstructionSelector::executeMatchTable(
break;
}

case GIM_Accept:
DEBUG(dbgs() << "GIM_Accept\n");
case GIM_CheckIsSafeToFold: {
int64_t InsnID = *Command++;
DEBUG(dbgs() << "GIM_CheckIsSafeToFold(MIs[" << InsnID << "])\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (!isObviouslySafeToFold(*State.MIs[InsnID]))
return false;
break;
}

case GIR_MutateOpcode: {
int64_t OldInsnID = *Command++;
int64_t NewInsnID = *Command++;
int64_t NewOpcode = *Command++;
assert((size_t)NewInsnID == OutMIs.size() &&
"Expected to store MIs in order");
OutMIs.push_back(
MachineInstrBuilder(*State.MIs[OldInsnID]->getParent()->getParent(),
State.MIs[OldInsnID]));
OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
DEBUG(dbgs() << "GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << NewOpcode << ")\n");
break;
}
case GIR_BuildMI: {
int64_t InsnID = *Command++;
int64_t Opcode = *Command++;
assert((size_t)InsnID == OutMIs.size() &&
"Expected to store MIs in order");
OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
DEBUG(dbgs() << "GIR_BuildMI(OutMIs[" << InsnID << "], " << Opcode
<< ")\n");
break;
}

case GIR_Copy: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
DEBUG(dbgs() << "GIR_Copy(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID
<< "], " << OpIdx << ")\n");
break;
}
case GIR_CopySubReg: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t SubRegIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
0, SubRegIdx);
DEBUG(dbgs() << "GIR_CopySubReg(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << OpIdx << ", " << SubRegIdx
<< ")\n");
break;
}
case GIR_AddImplicitDef: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitDef(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImplicitUse: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitUse(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddRegister: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addReg(RegNum);
DEBUG(dbgs() << "GIR_AddRegister(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImm: {
int64_t InsnID = *Command++;
int64_t Imm = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addImm(Imm);
DEBUG(dbgs() << "GIR_AddImm(OutMIs[" << InsnID << "], " << Imm << ")\n");
break;
}
case GIR_ComplexRenderer: {
int64_t InsnID = *Command++;
int64_t RendererID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
State.Renderers[RendererID](OutMIs[InsnID]);
DEBUG(dbgs() << "GIR_ComplexRenderer(OutMIs[" << InsnID << "], "
<< RendererID << ")\n");
break;
}

case GIR_ConstrainOperandRC: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t RCEnum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
*TRI.getRegClass(RCEnum), TII, TRI, RBI);
DEBUG(dbgs() << "GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], "
<< OpIdx << ", " << RCEnum << ")\n");
break;
}
case GIR_ConstrainSelectedInstOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
RBI);
DEBUG(dbgs() << "GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
<< "])\n");
break;
}
case GIR_MergeMemOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
for (const auto *FromMI : State.MIs)
for (const auto &MMO : FromMI->memoperands())
OutMIs[InsnID].addMemOperand(MMO);
DEBUG(dbgs() << "GIR_MergeMemOperands(OutMIs[" << InsnID << "])\n");
break;
}
case GIR_EraseFromParent: {
int64_t InsnID = *Command++;
assert(State.MIs[InsnID] &&
"Attempted to erase an undefined instruction");
State.MIs[InsnID]->eraseFromParent();
DEBUG(dbgs() << "GIR_EraseFromParent(MIs[" << InsnID << "])\n");
break;
}

case GIR_Done:
DEBUG(dbgs() << "GIR_Done");
return true;

default:
llvm_unreachable("Unexpected command");
}
Expand Down
149 changes: 0 additions & 149 deletions llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,155 +35,6 @@ InstructionSelector::MatcherState::MatcherState(unsigned MaxRenderers)

InstructionSelector::InstructionSelector() = default;

void InstructionSelector::executeEmitTable(NewMIVector &OutMIs,
MatcherState &State,
const int64_t *EmitTable,
const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const {
const int64_t *Command = EmitTable;
while (true) {
switch (*Command++) {
case GIR_MutateOpcode: {
int64_t OldInsnID = *Command++;
int64_t NewInsnID = *Command++;
int64_t NewOpcode = *Command++;
assert((size_t)NewInsnID == OutMIs.size() &&
"Expected to store MIs in order");
OutMIs.push_back(
MachineInstrBuilder(*State.MIs[OldInsnID]->getParent()->getParent(),
State.MIs[OldInsnID]));
OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
DEBUG(dbgs() << "GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << NewOpcode << ")\n");
break;
}
case GIR_BuildMI: {
int64_t InsnID LLVM_ATTRIBUTE_UNUSED = *Command++;
int64_t Opcode = *Command++;
assert((size_t)InsnID == OutMIs.size() &&
"Expected to store MIs in order");
OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
DEBUG(dbgs() << "GIR_BuildMI(OutMIs[" << InsnID << "], " << Opcode
<< ")\n");
break;
}

case GIR_Copy: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
DEBUG(dbgs() << "GIR_Copy(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID
<< "], " << OpIdx << ")\n");
break;
}
case GIR_CopySubReg: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t SubRegIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
0, SubRegIdx);
DEBUG(dbgs() << "GIR_CopySubReg(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << OpIdx << ", " << SubRegIdx
<< ")\n");
break;
}
case GIR_AddImplicitDef: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitDef(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImplicitUse: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitUse(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddRegister: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addReg(RegNum);
DEBUG(dbgs() << "GIR_AddRegister(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImm: {
int64_t InsnID = *Command++;
int64_t Imm = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addImm(Imm);
DEBUG(dbgs() << "GIR_AddImm(OutMIs[" << InsnID << "], " << Imm << ")\n");
break;
}
case GIR_ComplexRenderer: {
int64_t InsnID = *Command++;
int64_t RendererID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
State.Renderers[RendererID](OutMIs[InsnID]);
DEBUG(dbgs() << "GIR_ComplexRenderer(OutMIs[" << InsnID << "], "
<< RendererID << ")\n");
break;
}

case GIR_ConstrainOperandRC: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t RCEnum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
*TRI.getRegClass(RCEnum), TII, TRI, RBI);
DEBUG(dbgs() << "GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], "
<< OpIdx << ", " << RCEnum << ")\n");
break;
}
case GIR_ConstrainSelectedInstOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
RBI);
DEBUG(dbgs() << "GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
<< "])\n");
break;
}
case GIR_MergeMemOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
for (const auto *FromMI : State.MIs)
for (const auto &MMO : FromMI->memoperands())
OutMIs[InsnID].addMemOperand(MMO);
DEBUG(dbgs() << "GIR_MergeMemOperands(OutMIs[" << InsnID << "])\n");
break;
}
case GIR_EraseFromParent: {
int64_t InsnID = *Command++;
assert(State.MIs[InsnID] && "Attempted to erase an undefined instruction");
State.MIs[InsnID]->eraseFromParent();
DEBUG(dbgs() << "GIR_EraseFromParent(MIs[" << InsnID << "])\n");
break;
}

case GIR_Done:
DEBUG(dbgs() << "GIR_Done");
return;
default:
llvm_unreachable("Unexpected command");
}
}
}

bool InstructionSelector::constrainOperandRegToRegClass(
MachineInstr &I, unsigned OpIdx, const TargetRegisterClass &RC,
const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
Expand Down
Loading

0 comments on commit a6cfce6

Please sign in to comment.