mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[globalisel][tablegen] Added instruction emission to the state-machine-based matcher.
Summary: This further improves the compile-time regressions that will be caused by a re-commit of r303259. Also added included preliminary work in preparation for the multi-insn emitter since I needed to change the relevant part of the API for this patch anyway. Depends on D33758 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/D33764 llvm-svn: 307133
This commit is contained in:
parent
cfefb2f8af
commit
067ddbd8c9
@ -116,6 +116,69 @@ enum {
|
||||
GIM_Accept,
|
||||
};
|
||||
|
||||
enum {
|
||||
/// Mutate an instruction
|
||||
/// - NewInsnID - Instruction ID to define
|
||||
/// - OldInsnID - Instruction ID to mutate
|
||||
/// - NewOpcode - The new opcode to use
|
||||
GIR_MutateOpcode,
|
||||
/// Build a new instruction
|
||||
/// - InsnID - Instruction ID to define
|
||||
/// - Opcode - The new opcode to use
|
||||
GIR_BuildMI,
|
||||
|
||||
/// Copy an operand to the specified instruction
|
||||
/// - NewInsnID - Instruction ID to modify
|
||||
/// - OldInsnID - Instruction ID to copy from
|
||||
/// - OpIdx - The operand to copy
|
||||
GIR_Copy,
|
||||
/// Copy an operand to the specified instruction
|
||||
/// - NewInsnID - Instruction ID to modify
|
||||
/// - OldInsnID - Instruction ID to copy from
|
||||
/// - OpIdx - The operand to copy
|
||||
/// - SubRegIdx - The subregister to copy
|
||||
GIR_CopySubReg,
|
||||
/// Add an implicit register def to the specified instruction
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - RegNum - The register to add
|
||||
GIR_AddImplicitDef,
|
||||
/// Add an implicit register use to the specified instruction
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - RegNum - The register to add
|
||||
GIR_AddImplicitUse,
|
||||
/// Add an register to the specified instruction
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - RegNum - The register to add
|
||||
GIR_AddRegister,
|
||||
/// Add an immediate to the specified instruction
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - Imm - The immediate to add
|
||||
GIR_AddImm,
|
||||
/// Render complex operands to the specified instruction
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - RendererID - The renderer to call
|
||||
GIR_ComplexRenderer,
|
||||
|
||||
/// Constrain an instruction operand to a register class.
|
||||
/// - InsnID - Instruction ID to modify
|
||||
/// - OpIdx - Operand index
|
||||
/// - RCEnum - Register class enumeration value
|
||||
GIR_ConstrainOperandRC,
|
||||
/// Constrain an instructions operands according to the instruction
|
||||
/// description.
|
||||
/// - InsnID - Instruction ID to modify
|
||||
GIR_ConstrainSelectedInstOperands,
|
||||
/// Merge all memory operands into instruction.
|
||||
/// - InsnID - Instruction ID to modify
|
||||
GIR_MergeMemOperands,
|
||||
/// Erase from parent.
|
||||
/// - InsnID - Instruction ID to erase
|
||||
GIR_EraseFromParent,
|
||||
|
||||
/// A successful emission
|
||||
GIR_Done,
|
||||
};
|
||||
|
||||
/// Provides the logic to select generic machine instructions.
|
||||
class InstructionSelector {
|
||||
public:
|
||||
@ -137,6 +200,7 @@ public:
|
||||
protected:
|
||||
using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>;
|
||||
using RecordedMIVector = SmallVector<MachineInstr *, 4>;
|
||||
using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
|
||||
|
||||
struct MatcherState {
|
||||
std::vector<ComplexRendererFn> Renderers;
|
||||
@ -166,6 +230,10 @@ protected:
|
||||
const int64_t *MatchTable, 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
|
||||
|
@ -161,13 +161,14 @@ bool InstructionSelector::executeMatchTable(
|
||||
}
|
||||
|
||||
case GIM_Accept:
|
||||
DEBUG(dbgs() << "GIM_Accept");
|
||||
DEBUG(dbgs() << "GIM_Accept\n");
|
||||
return true;
|
||||
default:
|
||||
llvm_unreachable("Unexpected command");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
|
||||
|
@ -16,7 +16,11 @@
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
@ -31,6 +35,155 @@ 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 = *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,
|
||||
|
@ -107,19 +107,23 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable0\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable0, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, complex:i32:$src3) => (INSN2:i32 GPR32:i32:$src1, complex:i32:$src3, complex:i32:$src2)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN2));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: Renderers[1](MIB);
|
||||
// CHECK-NEXT: Renderers[0](MIB);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable0[] = {
|
||||
// CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, complex:i32:$src3) => (INSN2:i32 GPR32:i32:$src1, complex:i32:$src3, complex:i32:$src2)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/1,
|
||||
// CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable0\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable0, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -146,11 +150,17 @@ def : Pat<(select GPR32:$src1, complex:$src2, complex:$src3),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable1\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable1, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2)
|
||||
// CHECK-NEXT: I.setDesc(TII.get(MyTarget::ADD));
|
||||
// CHECK-NEXT: MachineInstr &NewI = I;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable1[] = {
|
||||
// CHECK-NEXT: // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2)
|
||||
// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/MyTarget::ADD,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable1\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable1, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -186,21 +196,25 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable2\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable2, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: if (!isObviouslySafeToFold(*State.MIs[1]))
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: // (mul:i32 (add:i32 GPR32:i32:$src1, GPR32:i32:$src2), GPR32:i32:$src3) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MULADD));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(2)/*src3*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], State.MIs[1], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable2[] = {
|
||||
// CHECK-NEXT: // (mul:i32 (add:i32 GPR32:i32:$src1, GPR32:i32:$src2), GPR32:i32:$src3) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src3
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable2\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable2, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -232,23 +246,27 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable3\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable3, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: if (!isObviouslySafeToFold(*State.MIs[1]))
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: // (mul:i32 GPR32:i32:$src3, (add:i32 GPR32:i32:$src1, GPR32:i32:$src2)) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MULADD));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src3*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], State.MIs[1], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: if (!isObviouslySafeToFold(*State.MIs[1]))
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: const static int64_t EmitTable3[] = {
|
||||
// CHECK-NEXT: // (mul:i32 GPR32:i32:$src3, (add:i32 GPR32:i32:$src1, GPR32:i32:$src2)) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src3
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable3\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable3, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
|
||||
[(set GPR32:$dst,
|
||||
@ -274,18 +292,22 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable4\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable4, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MUL));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(2)/*src2*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable4[] = {
|
||||
// CHECK-NEXT: // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MUL,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src2
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable4\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable4, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -332,24 +354,28 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable5\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable5, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: if (!isObviouslySafeToFold(*State.MIs[1]))
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: if (!isObviouslySafeToFold(*State.MIs[2]))
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: // (sub:i32 (sub:i32 GPR32:i32:$src1, GPR32:i32:$src2), (sub:i32 GPR32:i32:$src3, GPR32:i32:$src4)) => (INSNBOB:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3, GPR32:i32:$src4)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSNBOB));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[2]->getOperand(1)/*src3*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[2]->getOperand(2)/*src4*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], State.MIs[1], State.MIs[2], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable5[] = {
|
||||
// CHECK-NEXT: // (sub:i32 (sub:i32 GPR32:i32:$src1, GPR32:i32:$src2), (sub:i32 GPR32:i32:$src3, GPR32:i32:$src4)) => (INSNBOB:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3, GPR32:i32:$src4)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSNBOB,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/1, // src3
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // src4
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable5\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable5, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -377,18 +403,22 @@ def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, G
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable6\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable6, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN1));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: Renderers[0](MIB);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable6[] = {
|
||||
// CHECK-NEXT: // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN1,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable6\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable6, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -414,18 +444,22 @@ def : Pat<(sub GPR32:$src1, complex:$src2), (INSN1 GPR32:$src1, complex:$src2)>;
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable7\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable7, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -2:i32) => (XORI:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORI));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.addImm(-1);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable7[] = {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -2:i32) => (XORI:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORI,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable7\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable7, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -452,18 +486,22 @@ def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable8\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable8, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -3:i32) => (XOR:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XOR));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.addReg(MyTarget::R0);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable8[] = {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -3:i32) => (XOR:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XOR,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable8\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable8, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -490,19 +528,23 @@ def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable9\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable9, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -4:i32) => (XORlike:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORlike));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.addImm(-1);
|
||||
// CHECK-NEXT: MIB.addReg(MyTarget::R0);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable9[] = {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -4:i32) => (XORlike:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORlike,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
|
||||
// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable9\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable9, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -529,20 +571,24 @@ def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable10\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable10, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORManyDefaults));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.addImm(-1);
|
||||
// CHECK-NEXT: MIB.addReg(MyTarget::R0);
|
||||
// CHECK-NEXT: MIB.addReg(MyTarget::R0);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable10[] = {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORManyDefaults,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
|
||||
// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
|
||||
// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable10\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable10, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -571,18 +617,22 @@ def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1)
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable11\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable11, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::ORN));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: MIB.addReg(MyTarget::R0);
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(1)/*Wm*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable11[] = {
|
||||
// CHECK-NEXT: // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ORN,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // Wm
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable11\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable11, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -605,11 +655,17 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable12\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable12, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (bitconvert:i32 FPR32:f32:$src1) => (COPY_TO_REGCLASS:i32 FPR32:f32:$src1, GPR32:i32)
|
||||
// CHECK-NEXT: I.setDesc(TII.get(TargetOpcode::COPY));
|
||||
// CHECK-NEXT: MachineInstr &NewI = I;
|
||||
// CHECK-NEXT: constrainOperandRegToRegClass(NewI, 0, MyTarget::GPR32RegClass, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable12[] = {
|
||||
// CHECK-NEXT: // (bitconvert:i32 FPR32:f32:$src1) => (COPY_TO_REGCLASS:i32 FPR32:f32:$src1, GPR32:i32)
|
||||
// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/TargetOpcode::COPY,
|
||||
// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/ 1,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable12\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable12, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -630,16 +686,20 @@ def : Pat<(i32 (bitconvert FPR32:$src1)),
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable13\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable13, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // 1:i32 => (MOV1:i32)
|
||||
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MOV1));
|
||||
// CHECK-NEXT: MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
|
||||
// CHECK-NEXT: for (const auto *FromMI : {State.MIs[0], })
|
||||
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
|
||||
// CHECK-NEXT: MIB.addMemOperand(MMO);
|
||||
// CHECK-NEXT: I.eraseFromParent();
|
||||
// CHECK-NEXT: MachineInstr &NewI = *MIB;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: const static int64_t EmitTable13[] = {
|
||||
// CHECK-NEXT: // 1:i32 => (MOV1:i32)
|
||||
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV1,
|
||||
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
|
||||
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable13\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable13, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -656,12 +716,18 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: MIs.clear();
|
||||
// CHECK-NEXT: MIs.push_back(&I);
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing MatchTable14\n");
|
||||
// CHECK-NEXT: if (executeMatchTable(*this, State, MatcherInfo, MatchTable14, MRI, TRI, RBI, AvailableFeatures)) {
|
||||
// CHECK-NEXT: // (br (bb:Other):$target) => (BR (bb:Other):$target)
|
||||
// CHECK-NEXT: I.setDesc(TII.get(MyTarget::BR));
|
||||
// CHECK-NEXT: MachineInstr &NewI = I;
|
||||
// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: const static int64_t EmitTable14[] = {
|
||||
// CHECK-NEXT: // (br (bb:Other):$target) => (BR (bb:Other):$target)
|
||||
// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/MyTarget::BR,
|
||||
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
|
||||
// CHECK-NEXT: GIR_Done,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: NewMIVector OutMIs;
|
||||
// CHECK-NEXT: DEBUG(dbgs() << "Processing EmitTable14\n");
|
||||
// CHECK-NEXT: executeEmitTable(OutMIs, State, EmitTable14, TII, TRI, RBI);
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
def BR : I<(outs), (ins unknown:$target),
|
||||
|
@ -263,7 +263,6 @@ public:
|
||||
unsigned InsnVarID, unsigned OpIdx);
|
||||
unsigned getInsnVarID(const InstructionMatcher &InsnMatcher) const;
|
||||
|
||||
void emitCxxCapturedInsnList(raw_ostream &OS);
|
||||
void emitCxxCaptureStmts(raw_ostream &OS);
|
||||
|
||||
void emit(raw_ostream &OS);
|
||||
@ -906,6 +905,7 @@ public:
|
||||
/// instruction to the one being built.
|
||||
class CopyRenderer : public OperandRenderer {
|
||||
protected:
|
||||
unsigned NewInsnID;
|
||||
/// The matcher for the instruction that this operand is copied from.
|
||||
/// This provides the facility for looking up an a operand by it's name so
|
||||
/// that it can be used as a source for the instruction being built.
|
||||
@ -914,9 +914,10 @@ protected:
|
||||
const StringRef SymbolicName;
|
||||
|
||||
public:
|
||||
CopyRenderer(const InstructionMatcher &Matched, StringRef SymbolicName)
|
||||
: OperandRenderer(OR_Copy), Matched(Matched), SymbolicName(SymbolicName) {
|
||||
}
|
||||
CopyRenderer(unsigned NewInsnID, const InstructionMatcher &Matched,
|
||||
StringRef SymbolicName)
|
||||
: OperandRenderer(OR_Copy), NewInsnID(NewInsnID), Matched(Matched),
|
||||
SymbolicName(SymbolicName) {}
|
||||
|
||||
static bool classof(const OperandRenderer *R) {
|
||||
return R->getKind() == OR_Copy;
|
||||
@ -926,10 +927,10 @@ public:
|
||||
|
||||
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
|
||||
const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
|
||||
unsigned InsnVarID =
|
||||
Rule.getInsnVarID(Operand.getInstructionMatcher());
|
||||
std::string OperandExpr = Operand.getOperandExpr(InsnVarID);
|
||||
OS << " MIB.add(" << OperandExpr << "/*" << SymbolicName << "*/);\n";
|
||||
unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
|
||||
OS << " GIR_Copy, /*NewInsnID*/" << NewInsnID << ", /*OldInsnID*/"
|
||||
<< OldInsnVarID << ", /*OpIdx*/" << Operand.getOperandIndex() << ", // "
|
||||
<< SymbolicName << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -938,6 +939,7 @@ public:
|
||||
/// subregister should be copied.
|
||||
class CopySubRegRenderer : public OperandRenderer {
|
||||
protected:
|
||||
unsigned NewInsnID;
|
||||
/// The matcher for the instruction that this operand is copied from.
|
||||
/// This provides the facility for looking up an a operand by it's name so
|
||||
/// that it can be used as a source for the instruction being built.
|
||||
@ -948,9 +950,9 @@ protected:
|
||||
const CodeGenSubRegIndex *SubReg;
|
||||
|
||||
public:
|
||||
CopySubRegRenderer(const InstructionMatcher &Matched, StringRef SymbolicName,
|
||||
const CodeGenSubRegIndex *SubReg)
|
||||
: OperandRenderer(OR_CopySubReg), Matched(Matched),
|
||||
CopySubRegRenderer(unsigned NewInsnID, const InstructionMatcher &Matched,
|
||||
StringRef SymbolicName, const CodeGenSubRegIndex *SubReg)
|
||||
: OperandRenderer(OR_CopySubReg), NewInsnID(NewInsnID), Matched(Matched),
|
||||
SymbolicName(SymbolicName), SubReg(SubReg) {}
|
||||
|
||||
static bool classof(const OperandRenderer *R) {
|
||||
@ -961,10 +963,11 @@ public:
|
||||
|
||||
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
|
||||
const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
|
||||
unsigned InsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
|
||||
std::string OperandExpr = Operand.getOperandExpr(InsnVarID);
|
||||
OS << " MIB.addReg(" << OperandExpr << ".getReg() /*" << SymbolicName
|
||||
<< "*/, 0, " << SubReg->EnumValue << ");\n";
|
||||
unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
|
||||
OS << " GIR_CopySubReg, /*NewInsnID*/" << NewInsnID
|
||||
<< ", /*OldInsnID*/" << OldInsnVarID << ", /*OpIdx*/"
|
||||
<< Operand.getOperandIndex() << ", /*SubRegIdx*/" << SubReg->EnumValue
|
||||
<< ", // " << SymbolicName << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -972,39 +975,44 @@ public:
|
||||
/// This is typically useful for WZR/XZR on AArch64.
|
||||
class AddRegisterRenderer : public OperandRenderer {
|
||||
protected:
|
||||
unsigned InsnID;
|
||||
const Record *RegisterDef;
|
||||
|
||||
public:
|
||||
AddRegisterRenderer(const Record *RegisterDef)
|
||||
: OperandRenderer(OR_Register), RegisterDef(RegisterDef) {}
|
||||
AddRegisterRenderer(unsigned InsnID, const Record *RegisterDef)
|
||||
: OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef) {
|
||||
}
|
||||
|
||||
static bool classof(const OperandRenderer *R) {
|
||||
return R->getKind() == OR_Register;
|
||||
}
|
||||
|
||||
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
|
||||
OS << " MIB.addReg(" << (RegisterDef->getValue("Namespace")
|
||||
? RegisterDef->getValueAsString("Namespace")
|
||||
: "")
|
||||
<< "::" << RegisterDef->getName() << ");\n";
|
||||
OS << " GIR_AddRegister, /*InsnID*/" << InsnID << ", "
|
||||
<< (RegisterDef->getValue("Namespace")
|
||||
? RegisterDef->getValueAsString("Namespace")
|
||||
: "")
|
||||
<< "::" << RegisterDef->getName() << ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
/// Adds a specific immediate to the instruction being built.
|
||||
class ImmRenderer : public OperandRenderer {
|
||||
protected:
|
||||
unsigned InsnID;
|
||||
int64_t Imm;
|
||||
|
||||
public:
|
||||
ImmRenderer(int64_t Imm)
|
||||
: OperandRenderer(OR_Imm), Imm(Imm) {}
|
||||
ImmRenderer(unsigned InsnID, int64_t Imm)
|
||||
: OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {}
|
||||
|
||||
static bool classof(const OperandRenderer *R) {
|
||||
return R->getKind() == OR_Imm;
|
||||
}
|
||||
|
||||
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
|
||||
OS << " MIB.addImm(" << Imm << ");\n";
|
||||
OS << " GIR_AddImm, /*InsnID*/" << InsnID << ", /*Imm*/" << Imm
|
||||
<< ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1012,6 +1020,7 @@ public:
|
||||
/// matcher function.
|
||||
class RenderComplexPatternOperand : public OperandRenderer {
|
||||
private:
|
||||
unsigned InsnID;
|
||||
const Record &TheDef;
|
||||
/// The name of the operand.
|
||||
const StringRef SymbolicName;
|
||||
@ -1024,9 +1033,9 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
RenderComplexPatternOperand(const Record &TheDef, StringRef SymbolicName,
|
||||
unsigned RendererID)
|
||||
: OperandRenderer(OR_ComplexPattern), TheDef(TheDef),
|
||||
RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef,
|
||||
StringRef SymbolicName, unsigned RendererID)
|
||||
: OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef),
|
||||
SymbolicName(SymbolicName), RendererID(RendererID) {}
|
||||
|
||||
static bool classof(const OperandRenderer *R) {
|
||||
@ -1034,7 +1043,8 @@ public:
|
||||
}
|
||||
|
||||
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
|
||||
OS << " State.Renderers[" << RendererID << "](MIB);\n";
|
||||
OS << " GIR_ComplexRenderer, /*InsnID*/" << InsnID
|
||||
<< ", /*RendererID*/" << RendererID << ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1049,11 +1059,11 @@ public:
|
||||
|
||||
/// Emit the C++ statements to implement the action.
|
||||
///
|
||||
/// \param RecycleVarName If given, it's an instruction to recycle. The
|
||||
/// requirements on the instruction vary from action to
|
||||
/// action.
|
||||
/// \param RecycleInsnID If given, it's an instruction to recycle. The
|
||||
/// requirements on the instruction vary from action to
|
||||
/// action.
|
||||
virtual void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
|
||||
StringRef RecycleVarName) const = 0;
|
||||
unsigned RecycleInsnID) const = 0;
|
||||
};
|
||||
|
||||
/// Generates a comment describing the matched rule being acted upon.
|
||||
@ -1065,8 +1075,9 @@ public:
|
||||
DebugCommentAction(const PatternToMatch &P) : P(P) {}
|
||||
|
||||
void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
|
||||
StringRef RecycleVarName) const override {
|
||||
OS << " // " << *P.getSrcPattern() << " => " << *P.getDstPattern() << "\n";
|
||||
unsigned RecycleInsnID) const override {
|
||||
OS << " // " << *P.getSrcPattern() << " => " << *P.getDstPattern()
|
||||
<< "\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1074,7 +1085,7 @@ public:
|
||||
/// into the desired instruction when this is possible.
|
||||
class BuildMIAction : public MatchAction {
|
||||
private:
|
||||
std::string Name;
|
||||
unsigned InsnID;
|
||||
const CodeGenInstruction *I;
|
||||
const InstructionMatcher &Matched;
|
||||
std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;
|
||||
@ -1098,9 +1109,9 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
BuildMIAction(const StringRef Name, const CodeGenInstruction *I,
|
||||
BuildMIAction(unsigned InsnID, const CodeGenInstruction *I,
|
||||
const InstructionMatcher &Matched)
|
||||
: Name(Name), I(I), Matched(Matched) {}
|
||||
: InsnID(InsnID), I(I), Matched(Matched) {}
|
||||
|
||||
template <class Kind, class... Args>
|
||||
Kind &addRenderer(Args&&... args) {
|
||||
@ -1110,84 +1121,74 @@ public:
|
||||
}
|
||||
|
||||
void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
|
||||
StringRef RecycleVarName) const override {
|
||||
unsigned RecycleInsnID) const override {
|
||||
if (canMutate()) {
|
||||
OS << " " << RecycleVarName << ".setDesc(TII.get(" << I->Namespace
|
||||
<< "::" << I->TheDef->getName() << "));\n";
|
||||
OS << " GIR_MutateOpcode, /*InsnID*/" << InsnID
|
||||
<< ", /*RecycleInsnID*/ " << RecycleInsnID << ", /*Opcode*/"
|
||||
<< I->Namespace << "::" << I->TheDef->getName() << ",\n";
|
||||
|
||||
if (!I->ImplicitDefs.empty() || !I->ImplicitUses.empty()) {
|
||||
OS << " auto MIB = MachineInstrBuilder(MF, &" << RecycleVarName
|
||||
<< ");\n";
|
||||
|
||||
for (auto Def : I->ImplicitDefs) {
|
||||
auto Namespace = Def->getValue("Namespace")
|
||||
? Def->getValueAsString("Namespace")
|
||||
: "";
|
||||
OS << " MIB.addDef(" << Namespace << "::" << Def->getName()
|
||||
<< ", RegState::Implicit);\n";
|
||||
OS << " GIR_AddImplicitDef, " << InsnID << ", " << Namespace
|
||||
<< "::" << Def->getName() << ",\n";
|
||||
}
|
||||
for (auto Use : I->ImplicitUses) {
|
||||
auto Namespace = Use->getValue("Namespace")
|
||||
? Use->getValueAsString("Namespace")
|
||||
: "";
|
||||
OS << " MIB.addUse(" << Namespace << "::" << Use->getName()
|
||||
<< ", RegState::Implicit);\n";
|
||||
OS << " GIR_AddImplicitUse, " << InsnID << ", " << Namespace
|
||||
<< "::" << Use->getName() << ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
OS << " MachineInstr &" << Name << " = " << RecycleVarName << ";\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Simple permutation looks like it could be almost as common as
|
||||
// mutation due to commutative operations.
|
||||
|
||||
OS << " MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, "
|
||||
"I.getDebugLoc(), TII.get("
|
||||
<< I->Namespace << "::" << I->TheDef->getName() << "));\n";
|
||||
OS << " GIR_BuildMI, /*InsnID*/" << InsnID << ", /*Opcode*/"
|
||||
<< I->Namespace << "::" << I->TheDef->getName() << ",\n";
|
||||
for (const auto &Renderer : OperandRenderers)
|
||||
Renderer->emitCxxRenderStmts(OS, Rule);
|
||||
OS << " for (const auto *FromMI : ";
|
||||
Rule.emitCxxCapturedInsnList(OS);
|
||||
OS << ")\n";
|
||||
OS << " for (const auto &MMO : FromMI->memoperands())\n";
|
||||
OS << " MIB.addMemOperand(MMO);\n";
|
||||
OS << " " << RecycleVarName << ".eraseFromParent();\n";
|
||||
OS << " MachineInstr &" << Name << " = *MIB;\n";
|
||||
|
||||
OS << " GIR_MergeMemOperands, /*InsnID*/" << InsnID << ",\n"
|
||||
<< " GIR_EraseFromParent, /*InsnID*/" << RecycleInsnID << ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
/// Generates code to constrain the operands of an output instruction to the
|
||||
/// register classes specified by the definition of that instruction.
|
||||
class ConstrainOperandsToDefinitionAction : public MatchAction {
|
||||
std::string Name;
|
||||
unsigned InsnID;
|
||||
|
||||
public:
|
||||
ConstrainOperandsToDefinitionAction(const StringRef Name) : Name(Name) {}
|
||||
ConstrainOperandsToDefinitionAction(unsigned InsnID) : InsnID(InsnID) {}
|
||||
|
||||
void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
|
||||
StringRef RecycleVarName) const override {
|
||||
OS << " constrainSelectedInstRegOperands(" << Name
|
||||
<< ", TII, TRI, RBI);\n";
|
||||
unsigned RecycleInsnID) const override {
|
||||
OS << " GIR_ConstrainSelectedInstOperands, /*InsnID*/" << InsnID << ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
/// Generates code to constrain the specified operand of an output instruction
|
||||
/// to the specified register class.
|
||||
class ConstrainOperandToRegClassAction : public MatchAction {
|
||||
std::string Name;
|
||||
unsigned InsnID;
|
||||
unsigned OpIdx;
|
||||
const CodeGenRegisterClass &RC;
|
||||
|
||||
public:
|
||||
ConstrainOperandToRegClassAction(const StringRef Name, unsigned OpIdx,
|
||||
ConstrainOperandToRegClassAction(unsigned InsnID, unsigned OpIdx,
|
||||
const CodeGenRegisterClass &RC)
|
||||
: Name(Name), OpIdx(OpIdx), RC(RC) {}
|
||||
: InsnID(InsnID), OpIdx(OpIdx), RC(RC) {}
|
||||
|
||||
void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
|
||||
StringRef RecycleVarName) const override {
|
||||
OS << " constrainOperandRegToRegClass(" << Name << ", " << OpIdx
|
||||
<< ", " << RC.getQualifiedName() << "RegClass, TII, TRI, RBI);\n";
|
||||
unsigned RecycleInsnID) const override {
|
||||
OS << " GIR_ConstrainOperandRC, /*InsnID*/" << InsnID << ", /*Op*/"
|
||||
<< OpIdx << ", /*RC " << RC.getName() << "*/ " << RC.EnumValue << ",\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -1234,20 +1235,6 @@ unsigned RuleMatcher::getInsnVarID(const InstructionMatcher &InsnMatcher) const
|
||||
llvm_unreachable("Matched Insn was not captured in a local variable");
|
||||
}
|
||||
|
||||
/// Emit a C++ initializer_list containing references to every matched
|
||||
/// instruction.
|
||||
void RuleMatcher::emitCxxCapturedInsnList(raw_ostream &OS) {
|
||||
SmallVector<unsigned, 2> IDs;
|
||||
for (const auto &Pair : InsnVariableIDs)
|
||||
IDs.push_back(Pair.second);
|
||||
std::sort(IDs.begin(), IDs.end());
|
||||
|
||||
OS << "{";
|
||||
for (const auto &ID : IDs)
|
||||
OS << "State.MIs[" << ID << "], ";
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
/// Emit C++ statements to check the shape of the match and capture
|
||||
/// instructions into local variables.
|
||||
void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS) {
|
||||
@ -1287,6 +1274,8 @@ void RuleMatcher::emit(raw_ostream &OS) {
|
||||
<< " };\n"
|
||||
<< " State.MIs.clear();\n"
|
||||
<< " State.MIs.push_back(&I);\n"
|
||||
<< " DEBUG(dbgs() << \"Processing MatchTable" << NumPatternEmitted
|
||||
<< "\\n\");\n"
|
||||
<< " if (executeMatchTable(*this, State, MatcherInfo, MatchTable"
|
||||
<< CurrentMatchTableID << ", MRI, TRI, RBI, AvailableFeatures)) {\n";
|
||||
|
||||
@ -1346,9 +1335,16 @@ void RuleMatcher::emit(raw_ostream &OS) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &MA : Actions) {
|
||||
MA->emitCxxActionStmts(OS, *this, "I");
|
||||
}
|
||||
OS << " const static int64_t EmitTable" << NumPatternEmitted << "[] = {\n";
|
||||
for (const auto &MA : Actions)
|
||||
MA->emitCxxActionStmts(OS, *this, 0);
|
||||
OS << " GIR_Done,\n"
|
||||
<< " };\n"
|
||||
<< " NewMIVector OutMIs;\n"
|
||||
<< " DEBUG(dbgs() << \"Processing EmitTable" << NumPatternEmitted
|
||||
<< "\\n\");\n"
|
||||
<< " executeEmitTable(OutMIs, State, EmitTable" << NumPatternEmitted
|
||||
<< ", TII, TRI, RBI);\n";
|
||||
|
||||
OS << " return true;\n";
|
||||
OS << " }\n\n";
|
||||
@ -1625,7 +1621,7 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
|
||||
if (DstChild->getOperator()->isSubClassOf("SDNode")) {
|
||||
auto &ChildSDNI = CGP.getSDNodeInfo(DstChild->getOperator());
|
||||
if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher,
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher,
|
||||
DstChild->getName());
|
||||
return Error::success();
|
||||
}
|
||||
@ -1650,13 +1646,14 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
|
||||
return failedImport("Dst operand has an unsupported type");
|
||||
|
||||
if (ChildRec->isSubClassOf("Register")) {
|
||||
DstMIBuilder.addRenderer<AddRegisterRenderer>(ChildRec);
|
||||
DstMIBuilder.addRenderer<AddRegisterRenderer>(0, ChildRec);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
if (ChildRec->isSubClassOf("RegisterClass") ||
|
||||
ChildRec->isSubClassOf("RegisterOperand")) {
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstChild->getName());
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher,
|
||||
DstChild->getName());
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
@ -1668,7 +1665,7 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
|
||||
|
||||
const OperandMatcher &OM = InsnMatcher.getOperand(DstChild->getName());
|
||||
DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
|
||||
*ComplexPattern->second, DstChild->getName(),
|
||||
0, *ComplexPattern->second, DstChild->getName(),
|
||||
OM.getAllocatedTemporariesBaseID());
|
||||
return Error::success();
|
||||
}
|
||||
@ -1711,12 +1708,12 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
|
||||
IsExtractSubReg = true;
|
||||
}
|
||||
|
||||
auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher);
|
||||
auto &DstMIBuilder = M.addAction<BuildMIAction>(0, DstI, InsnMatcher);
|
||||
|
||||
// Render the explicit defs.
|
||||
for (unsigned I = 0; I < DstI->Operands.NumDefs; ++I) {
|
||||
const CGIOperandList::OperandInfo &DstIOperand = DstI->Operands[I];
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);
|
||||
DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, DstIOperand.Name);
|
||||
}
|
||||
|
||||
// EXTRACT_SUBREG needs to use a subregister COPY.
|
||||
@ -1739,7 +1736,7 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
|
||||
}
|
||||
|
||||
DstMIBuilder.addRenderer<CopySubRegRenderer>(
|
||||
InsnMatcher, Dst->getChild(0)->getName(), SubIdx);
|
||||
0, InsnMatcher, Dst->getChild(0)->getName(), SubIdx);
|
||||
return DstMIBuilder;
|
||||
}
|
||||
|
||||
@ -1795,12 +1792,12 @@ Error GlobalISelEmitter::importDefaultOperandRenderers(
|
||||
}
|
||||
|
||||
if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
|
||||
DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef());
|
||||
DstMIBuilder.addRenderer<AddRegisterRenderer>(0, DefaultDefOp->getDef());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const IntInit *DefaultIntOp = dyn_cast<IntInit>(DefaultOp)) {
|
||||
DstMIBuilder.addRenderer<ImmRenderer>(DefaultIntOp->getValue());
|
||||
DstMIBuilder.addRenderer<ImmRenderer>(0, DefaultIntOp->getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1919,7 +1916,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class");
|
||||
|
||||
M.addAction<ConstrainOperandToRegClassAction>(
|
||||
"NewI", 0, Target.getRegisterClass(DstIOpRec));
|
||||
0, 0, Target.getRegisterClass(DstIOpRec));
|
||||
|
||||
// We're done with this pattern! It's eligible for GISel emission; return
|
||||
// it.
|
||||
@ -1947,8 +1944,7 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
return failedImport("EXTRACT_SUBREG operand #1 isn't a register class");
|
||||
|
||||
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
|
||||
CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(
|
||||
getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));
|
||||
CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(DstIOpRec);
|
||||
|
||||
// It would be nice to leave this constraint implicit but we're required
|
||||
// to pick a register class so constrain the result to a register class
|
||||
@ -1962,12 +1958,16 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
|
||||
const auto &SrcRCDstRCPair =
|
||||
SrcRC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
|
||||
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
|
||||
M.addAction<ConstrainOperandToRegClassAction>("NewI", 0,
|
||||
*SrcRCDstRCPair->second);
|
||||
M.addAction<ConstrainOperandToRegClassAction>("NewI", 1,
|
||||
*SrcRCDstRCPair->first);
|
||||
} else
|
||||
M.addAction<ConstrainOperandsToDefinitionAction>("NewI");
|
||||
M.addAction<ConstrainOperandToRegClassAction>(0, 0, *SrcRCDstRCPair->second);
|
||||
M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first);
|
||||
|
||||
// We're done with this pattern! It's eligible for GISel emission; return
|
||||
// it.
|
||||
++NumPatternImported;
|
||||
return std::move(M);
|
||||
}
|
||||
|
||||
M.addAction<ConstrainOperandsToDefinitionAction>(0);
|
||||
|
||||
// We're done with this pattern! It's eligible for GISel emission; return it.
|
||||
++NumPatternImported;
|
||||
|
Loading…
Reference in New Issue
Block a user