mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-14 14:56:47 +00:00
CodeGen: improve MachineInstrBuilder & MachineIRBuilder interface
For MachineInstrBuilder, having to manually use RegState::Define is ugly and makes register definitions clunkier than they need to be, so this adds two convenience functions: addDef and addUse. For MachineIRBuilder, we want to avoid BuildMI's first-reg-is-def rule because it's hidden away and causes bugs. So this patch switches buildInstr to returning a MachineInstrBuilder and adding *all* operands via addDef/addUse. NFC. llvm-svn: 277176
This commit is contained in:
parent
48c7cc9bc0
commit
a51575ffa2
@ -52,16 +52,6 @@ class MachineIRBuilder {
|
||||
return *TII;
|
||||
}
|
||||
|
||||
static void addRegs(MachineInstrBuilder &MIB) {}
|
||||
|
||||
template <typename... MoreRegs>
|
||||
static void addRegs(MachineInstrBuilder &MIB, unsigned Reg,
|
||||
MoreRegs... Regs) {
|
||||
MIB.addReg(Reg);
|
||||
addRegs(MIB, Regs...);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/// Getter for the function we currently build.
|
||||
MachineFunction &getMF() {
|
||||
@ -107,53 +97,19 @@ public:
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre Ty == LLT{} or isPreISelGenericOpcode(Opcode)
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildInstr(unsigned Opcode, ArrayRef<LLT> Tys);
|
||||
|
||||
/// Build and insert \p Res = \p Opcode [\p Ty] \p Uses....
|
||||
/// \p Ty is the type of the instruction if \p Opcode describes
|
||||
/// a generic machine instruction. \p Ty must be LLT{} if \p Opcode
|
||||
/// does not describe a generic instruction.
|
||||
/// The insertion point is the one set by the last call of either
|
||||
/// setBasicBlock or setMI.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre Ty == LLT{} or isPreISelGenericOpcode(Opcode)
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
template <typename... MoreRegs>
|
||||
MachineInstr *buildInstr(unsigned Opcode, ArrayRef<LLT> Tys, unsigned Res,
|
||||
MoreRegs... Uses) {
|
||||
MachineInstr *NewMI = buildInstr(Opcode, Tys);
|
||||
MachineInstrBuilder MIB{getMF(), NewMI};
|
||||
MIB.addReg(Res, RegState::Define);
|
||||
addRegs(MIB, Uses...);
|
||||
|
||||
return NewMI;
|
||||
}
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildInstr(unsigned Opcode, ArrayRef<LLT> Tys);
|
||||
|
||||
/// Build and insert <empty> = \p Opcode <empty>.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre not isPreISelGenericOpcode(\p Opcode)
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildInstr(unsigned Opcode) {
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildInstr(unsigned Opcode) {
|
||||
return buildInstr(Opcode, ArrayRef<LLT>());
|
||||
}
|
||||
|
||||
/// Build and insert \p Res = \p Opcode \p Uses....
|
||||
/// The insertion point is the one set by the last call of either
|
||||
/// setBasicBlock or setMI.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
template <typename... MoreRegs>
|
||||
MachineInstr *buildInstr(unsigned Opcode, unsigned Res, MoreRegs... Uses) {
|
||||
return buildInstr(Opcode, ArrayRef<LLT>(), Res, Uses...);
|
||||
}
|
||||
|
||||
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Ty \p Idx
|
||||
///
|
||||
/// G_FRAME_INDEX materializes the address of an alloca value or other
|
||||
@ -161,8 +117,8 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildFrameIndex(LLT Ty, unsigned Res, int Idx);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildFrameIndex(LLT Ty, unsigned Res, int Idx);
|
||||
|
||||
/// Build and insert \p Res<def> = G_ADD \p Ty \p Op0, \p Op1
|
||||
///
|
||||
@ -171,8 +127,9 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildAdd(LLT Ty, unsigned Res, unsigned Op0, unsigned Op1);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildAdd(LLT Ty, unsigned Res, unsigned Op0,
|
||||
unsigned Op1);
|
||||
|
||||
/// Build and insert G_BR unsized \p Dest
|
||||
///
|
||||
@ -180,8 +137,8 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildBr(MachineBasicBlock &BB);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildBr(MachineBasicBlock &BB);
|
||||
|
||||
/// Build and insert \p Res<def> = COPY Op
|
||||
///
|
||||
@ -189,8 +146,8 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildCopy(unsigned Res, unsigned Op);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildCopy(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert `Res<def> = G_LOAD { VTy, PTy } Addr, MMO`.
|
||||
///
|
||||
@ -199,9 +156,9 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildLoad(LLT VTy, LLT PTy, unsigned Res, unsigned Addr,
|
||||
MachineMemOperand &MMO);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildLoad(LLT VTy, LLT PTy, unsigned Res, unsigned Addr,
|
||||
MachineMemOperand &MMO);
|
||||
|
||||
/// Build and insert `G_STORE { VTy, PTy } Val, Addr, MMO`.
|
||||
///
|
||||
@ -210,9 +167,9 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildStore(LLT VTy, LLT PTy, unsigned Val, unsigned Addr,
|
||||
MachineMemOperand &MMO);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildStore(LLT VTy, LLT PTy, unsigned Val, unsigned Addr,
|
||||
MachineMemOperand &MMO);
|
||||
|
||||
/// Build and insert `Res0<def>, ... = G_EXTRACT Ty Src, Idx0, ...`.
|
||||
///
|
||||
@ -221,9 +178,9 @@ public:
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src,
|
||||
ArrayRef<unsigned> Indexes);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildExtract(LLT Ty, ArrayRef<unsigned> Results,
|
||||
unsigned Src, ArrayRef<unsigned> Indexes);
|
||||
|
||||
/// Build and insert \p Res<def> = G_SEQUENCE \p Ty \p Ops[0], ...
|
||||
///
|
||||
@ -233,8 +190,9 @@ public:
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre The sum of the input sizes must equal the result's size.
|
||||
///
|
||||
/// \return The newly created instruction.
|
||||
MachineInstr *buildSequence(LLT Ty, unsigned Res, ArrayRef<unsigned> Ops);
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildSequence(LLT Ty, unsigned Res,
|
||||
ArrayRef<unsigned> Ops);
|
||||
};
|
||||
|
||||
} // End namespace llvm.
|
||||
|
@ -83,6 +83,21 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Add a virtual register definition operand.
|
||||
const MachineInstrBuilder &addDef(unsigned RegNo, unsigned Flags = 0,
|
||||
unsigned SubReg = 0) const {
|
||||
return addReg(RegNo, Flags | RegState::Define, SubReg);
|
||||
}
|
||||
|
||||
/// Add a virtual register use operand. It is an error for Flags to contain
|
||||
/// `RegState::Define` when calling this function.
|
||||
const MachineInstrBuilder &addUse(unsigned RegNo, unsigned Flags = 0,
|
||||
unsigned SubReg = 0) const {
|
||||
assert(!(Flags & RegState::Define) &&
|
||||
"Misleading addUse defines register, use addReg instead.");
|
||||
return addReg(RegNo, Flags, SubReg);
|
||||
}
|
||||
|
||||
/// Add a new immediate operand.
|
||||
const MachineInstrBuilder &addImm(int64_t Val) const {
|
||||
MI->addOperand(*MF, MachineOperand::CreateImm(Val));
|
||||
|
@ -85,7 +85,10 @@ bool IRTranslator::translateBinaryOp(unsigned Opcode, const Instruction &Inst) {
|
||||
unsigned Op0 = getOrCreateVReg(*Inst.getOperand(0));
|
||||
unsigned Op1 = getOrCreateVReg(*Inst.getOperand(1));
|
||||
unsigned Res = getOrCreateVReg(Inst);
|
||||
MIRBuilder.buildInstr(Opcode, LLT{*Inst.getType()}, Res, Op0, Op1);
|
||||
MIRBuilder.buildInstr(Opcode, LLT{*Inst.getType()})
|
||||
.addDef(Res)
|
||||
.addUse(Op0)
|
||||
.addUse(Op1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -160,8 +163,9 @@ bool IRTranslator::translateBitCast(const CastInst &CI) {
|
||||
bool IRTranslator::translateCast(unsigned Opcode, const CastInst &CI) {
|
||||
unsigned Op = getOrCreateVReg(*CI.getOperand(0));
|
||||
unsigned Res = getOrCreateVReg(CI);
|
||||
MIRBuilder.buildInstr(Opcode, {LLT{*CI.getDestTy()}, LLT{*CI.getSrcTy()}},
|
||||
Res, Op);
|
||||
MIRBuilder.buildInstr(Opcode, {LLT{*CI.getDestTy()}, LLT{*CI.getSrcTy()}})
|
||||
.addDef(Res)
|
||||
.addUse(Op);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,83 +57,83 @@ MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() {
|
||||
// Build instruction variants.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, ArrayRef<LLT> Tys) {
|
||||
MachineInstr *NewMI = BuildMI(getMF(), DL, getTII().get(Opcode));
|
||||
MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode,
|
||||
ArrayRef<LLT> Tys) {
|
||||
MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode));
|
||||
if (Tys.size() > 0) {
|
||||
assert(isPreISelGenericOpcode(Opcode) &&
|
||||
"Only generic instruction can have a type");
|
||||
for (unsigned i = 0; i < Tys.size(); ++i)
|
||||
NewMI->setType(Tys[i], i);
|
||||
MIB->setType(Tys[i], i);
|
||||
} else
|
||||
assert(!isPreISelGenericOpcode(Opcode) &&
|
||||
"Generic instruction must have a type");
|
||||
getMBB().insert(getInsertPt(), NewMI);
|
||||
return NewMI;
|
||||
getMBB().insert(getInsertPt(), MIB);
|
||||
return MIB;
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res, int Idx) {
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_FRAME_INDEX, Ty);
|
||||
auto MIB = MachineInstrBuilder(getMF(), NewMI);
|
||||
MIB.addReg(Res, RegState::Define);
|
||||
MIB.addFrameIndex(Idx);
|
||||
return NewMI;
|
||||
MachineInstrBuilder MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res,
|
||||
int Idx) {
|
||||
return buildInstr(TargetOpcode::G_FRAME_INDEX, Ty)
|
||||
.addDef(Res)
|
||||
.addFrameIndex(Idx);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildAdd(LLT Ty, unsigned Res, unsigned Op0,
|
||||
unsigned Op1) {
|
||||
return buildInstr(TargetOpcode::G_ADD, Ty, Res, Op0, Op1);
|
||||
MachineInstrBuilder MachineIRBuilder::buildAdd(LLT Ty, unsigned Res,
|
||||
unsigned Op0, unsigned Op1) {
|
||||
return buildInstr(TargetOpcode::G_ADD, Ty)
|
||||
.addDef(Res)
|
||||
.addUse(Op0)
|
||||
.addUse(Op1);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_BR, LLT::unsized());
|
||||
MachineInstrBuilder(getMF(), NewMI).addMBB(&Dest);
|
||||
return NewMI;
|
||||
MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
|
||||
return buildInstr(TargetOpcode::G_BR, LLT::unsized()).addMBB(&Dest);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
|
||||
return buildInstr(TargetOpcode::COPY, Res, Op);
|
||||
MachineInstrBuilder MachineIRBuilder::buildCopy(unsigned Res, unsigned Op) {
|
||||
return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res,
|
||||
unsigned Addr,
|
||||
MachineMemOperand &MMO) {
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_LOAD, {VTy, PTy}, Res, Addr);
|
||||
NewMI->addMemOperand(getMF(), &MMO);
|
||||
return NewMI;
|
||||
MachineInstrBuilder MachineIRBuilder::buildLoad(LLT VTy, LLT PTy, unsigned Res,
|
||||
unsigned Addr,
|
||||
MachineMemOperand &MMO) {
|
||||
return buildInstr(TargetOpcode::G_LOAD, {VTy, PTy})
|
||||
.addDef(Res)
|
||||
.addUse(Addr)
|
||||
.addMemOperand(&MMO);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildStore(LLT VTy, LLT PTy, unsigned Val,
|
||||
unsigned Addr,
|
||||
MachineMemOperand &MMO) {
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_STORE, {VTy, PTy});
|
||||
NewMI->addMemOperand(getMF(), &MMO);
|
||||
MachineInstrBuilder(getMF(), NewMI).addReg(Val).addReg(Addr);
|
||||
return NewMI;
|
||||
MachineInstrBuilder MachineIRBuilder::buildStore(LLT VTy, LLT PTy,
|
||||
unsigned Val, unsigned Addr,
|
||||
MachineMemOperand &MMO) {
|
||||
return buildInstr(TargetOpcode::G_STORE, {VTy, PTy})
|
||||
.addUse(Val)
|
||||
.addUse(Addr)
|
||||
.addMemOperand(&MMO);
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results,
|
||||
unsigned Src,
|
||||
ArrayRef<unsigned> Indexes) {
|
||||
MachineInstrBuilder
|
||||
MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src,
|
||||
ArrayRef<unsigned> Indexes) {
|
||||
assert(Results.size() == Indexes.size() && "inconsistent number of regs");
|
||||
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_EXTRACT, Ty);
|
||||
auto MIB = MachineInstrBuilder(getMF(), NewMI);
|
||||
MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_EXTRACT, Ty);
|
||||
for (auto Res : Results)
|
||||
MIB.addReg(Res, RegState::Define);
|
||||
MIB.addDef(Res);
|
||||
|
||||
MIB.addReg(Src);
|
||||
MIB.addUse(Src);
|
||||
|
||||
for (auto Idx : Indexes)
|
||||
MIB.addImm(Idx);
|
||||
return NewMI;
|
||||
return MIB;
|
||||
}
|
||||
|
||||
MachineInstr *MachineIRBuilder::buildSequence(LLT Ty, unsigned Res,
|
||||
MachineInstrBuilder MachineIRBuilder::buildSequence(LLT Ty, unsigned Res,
|
||||
ArrayRef<unsigned> Ops) {
|
||||
MachineInstr *NewMI = buildInstr(TargetOpcode::G_SEQUENCE, Ty);
|
||||
auto MIB = MachineInstrBuilder(getMF(), NewMI);
|
||||
MIB.addReg(Res, RegState::Define);
|
||||
MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE, Ty);
|
||||
MIB.addDef(Res);
|
||||
for (auto Op : Ops)
|
||||
MIB.addReg(Op);
|
||||
return NewMI;
|
||||
MIB.addUse(Op);
|
||||
return MIB;
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
||||
unsigned ResReg = (Size == 32) ? AArch64::W0 : AArch64::X0;
|
||||
// Set the insertion point to be right before Return.
|
||||
MIRBuilder.setInstr(*Return, /* Before */ true);
|
||||
MachineInstr *Copy =
|
||||
MIRBuilder.buildInstr(TargetOpcode::COPY, ResReg, VReg);
|
||||
MachineInstr *Copy = MIRBuilder.buildCopy(ResReg, VReg);
|
||||
(void)Copy;
|
||||
assert(Copy->getNextNode() == Return &&
|
||||
"The insertion did not happen where we expected");
|
||||
@ -85,7 +84,7 @@ bool AArch64CallLowering::lowerFormalArguments(
|
||||
assert(VA.isRegLoc() && "Not yet implemented");
|
||||
// Transform the arguments in physical registers into virtual ones.
|
||||
MIRBuilder.getMBB().addLiveIn(VA.getLocReg());
|
||||
MIRBuilder.buildInstr(TargetOpcode::COPY, VRegs[i], VA.getLocReg());
|
||||
MIRBuilder.buildCopy(VRegs[i], VA.getLocReg());
|
||||
|
||||
switch (VA.getLocInfo()) {
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user