[llvm] 6ff3b43 - [TableGen] More generically handle tied source operands in CompressInstEmitter. (#146183)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 2 13:09:39 PDT 2025
Author: Craig Topper
Date: 2025-07-02T13:09:35-07:00
New Revision: 6ff3b43700175dbff8f2e4b63c6f27835418e20c
URL: https://github.com/llvm/llvm-project/commit/6ff3b43700175dbff8f2e4b63c6f27835418e20c
DIFF: https://github.com/llvm/llvm-project/commit/6ff3b43700175dbff8f2e4b63c6f27835418e20c.diff
LOG: [TableGen] More generically handle tied source operands in CompressInstEmitter. (#146183)
Move the creation of OperandMap from createDagOperandMapping to the loop
in addDagOperandMapping. Expand it to store the DAG operand number and
the MI operand number which will be different when there are tied
operands.
Rename createDagOperandMapping to checkDagOperandMapping to better
describe the remaining code.
I didn't lift the restriction that a source instruction can only have
one tied operand, but we should be able to if we have a use case.
There's a slight difference in the generate output. We now check that
operand 0 and 2 of QC_MVEQI are equal instead of operand 1 and 2. This
should be equivalent since operand 0 and 1 have a tied constraint.
Added:
Modified:
llvm/utils/TableGen/CompressInstEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp
index d3e98b3096afe..e73ea71ba14b5 100644
--- a/llvm/utils/TableGen/CompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/CompressInstEmitter.cpp
@@ -98,6 +98,10 @@ class CompressInstEmitter {
// Tied operand index within the instruction.
int TiedOpIdx = -1;
};
+ struct ArgData {
+ unsigned DAGOpNo;
+ unsigned MIOpNo;
+ };
struct CompressPat {
// The source instruction definition.
CodeGenInstruction Source;
@@ -126,27 +130,23 @@ class CompressInstEmitter {
std::vector<CompressPat> CompressPatterns;
void addDagOperandMapping(const Record *Rec, const DagInit *Dag,
const CodeGenInstruction &Inst,
- IndexedMap<OpData> &OperandMap, bool IsSourceInst,
- unsigned *SourceLastTiedOpPtr);
+ IndexedMap<OpData> &OperandMap,
+ StringMap<ArgData> &Operands, bool IsSourceInst);
void evaluateCompressPat(const Record *Compress);
void emitCompressInstEmitter(raw_ostream &OS, EmitterType EType);
bool validateTypes(const Record *DagOpType, const Record *InstOpType,
bool IsSourceInst);
bool validateRegister(const Record *Reg, const Record *RegClass);
- void createDagOperandMapping(const Record *Rec,
- StringMap<unsigned> &SourceOperands,
- StringMap<unsigned> &DestOperands,
- const DagInit *SourceDag, const DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap,
- bool HasSourceTiedOp);
+ void checkDagOperandMapping(const Record *Rec,
+ const StringMap<ArgData> &DestOperands,
+ const DagInit *SourceDag, const DagInit *DestDag);
void createInstOperandMapping(const Record *Rec, const DagInit *SourceDag,
const DagInit *DestDag,
IndexedMap<OpData> &SourceOperandMap,
IndexedMap<OpData> &DestOperandMap,
- StringMap<unsigned> &SourceOperands,
- const CodeGenInstruction &DestInst,
- unsigned SourceLastTiedOp);
+ StringMap<ArgData> &SourceOperands,
+ const CodeGenInstruction &DestInst);
public:
CompressInstEmitter(const RecordKeeper &R) : Records(R), Target(R) {}
@@ -198,6 +198,10 @@ bool CompressInstEmitter::validateTypes(const Record *DagOpType,
return true;
}
+static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) {
+ return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef();
+}
+
/// The patterns in the Dag contain
diff erent types of operands:
/// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
/// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
@@ -209,8 +213,8 @@ void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
const DagInit *Dag,
const CodeGenInstruction &Inst,
IndexedMap<OpData> &OperandMap,
- bool IsSourceInst,
- unsigned *SourceLastTiedOpPtr) {
+ StringMap<ArgData> &Operands,
+ bool IsSourceInst) {
unsigned NumMIOperands = 0;
if (!Inst.Operands.empty())
NumMIOperands =
@@ -224,16 +228,12 @@ void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
// are represented.
unsigned TiedCount = 0;
unsigned OpNo = 0;
- if (IsSourceInst)
- *SourceLastTiedOpPtr = std::numeric_limits<unsigned int>::max();
for (const auto &Opnd : Inst.Operands) {
int TiedOpIdx = Opnd.getTiedRegister();
if (-1 != TiedOpIdx) {
assert((unsigned)TiedOpIdx < OpNo);
// Set the entry in OperandMap for the tied operand we're skipping.
OperandMap[OpNo] = OperandMap[TiedOpIdx];
- if (IsSourceInst)
- *SourceLastTiedOpPtr = OpNo;
++OpNo;
++TiedCount;
continue;
@@ -290,6 +290,30 @@ void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
} else {
llvm_unreachable("Unhandled CompressPat argument type!");
}
+
+ // Create a mapping between the operand name in the Dag (e.g. $rs1) and
+ // its index in the list of Dag operands and check that operands with the
+ // same name have the same type. For example in 'C_ADD $rs1, $rs2' we
+ // generate the mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears
+ // twice in the same Dag (tied in the compressed instruction), we note
+ // the previous index in the TiedOpIdx field.
+ StringRef ArgName = Dag->getArgNameStr(DAGOpNo);
+ if (ArgName.empty())
+ continue;
+
+ if (IsSourceInst) {
+ auto It = Operands.find(ArgName);
+ if (It != Operands.end()) {
+ OperandMap[OpNo].TiedOpIdx = It->getValue().MIOpNo;
+ if (!validateArgsTypes(Dag->getArg(It->getValue().DAGOpNo),
+ Dag->getArg(DAGOpNo)))
+ PrintFatalError(Rec->getLoc(),
+ "Input Operand '" + ArgName +
+ "' has a mismatched tied operand!");
+ }
+ }
+
+ Operands[ArgName] = {DAGOpNo, OpNo};
}
}
}
@@ -331,60 +355,29 @@ static bool verifyDagOpCount(const CodeGenInstruction &Inst, const DagInit *Dag,
return true;
}
-static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) {
- return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef();
-}
-
-// Creates a mapping between the operand name in the Dag (e.g. $rs1) and
-// its index in the list of Dag operands and checks that operands with the same
-// name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
-// mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
-// same Dag we use the last occurrence for indexing.
-void CompressInstEmitter::createDagOperandMapping(
- const Record *Rec, StringMap<unsigned> &SourceOperands,
- StringMap<unsigned> &DestOperands, const DagInit *SourceDag,
- const DagInit *DestDag, IndexedMap<OpData> &SourceOperandMap,
- bool HasSourceTiedOp) {
- for (unsigned I = 0; I < DestDag->getNumArgs(); ++I) {
- // Skip fixed immediates and registers, they were handled in
- // addDagOperandMapping.
- if ("" == DestDag->getArgNameStr(I))
- continue;
- DestOperands[DestDag->getArgNameStr(I)] = I;
- }
+// Check that all names in the source DAG appear in the destionation DAG.
+void CompressInstEmitter::checkDagOperandMapping(
+ const Record *Rec, const StringMap<ArgData> &DestOperands,
+ const DagInit *SourceDag, const DagInit *DestDag) {
for (unsigned I = 0; I < SourceDag->getNumArgs(); ++I) {
// Skip fixed immediates and registers, they were handled in
// addDagOperandMapping.
- if ("" == SourceDag->getArgNameStr(I))
+ StringRef ArgName = SourceDag->getArgNameStr(I);
+ if (ArgName.empty())
continue;
- StringMap<unsigned>::iterator It =
- SourceOperands.find(SourceDag->getArgNameStr(I));
- if (It != SourceOperands.end()) {
- // Operand sharing the same name in the Dag should be mapped as tied.
- if (HasSourceTiedOp)
- SourceOperandMap[I + 1].TiedOpIdx = It->getValue() + 1;
- else
- SourceOperandMap[I].TiedOpIdx = It->getValue();
- if (!validateArgsTypes(SourceDag->getArg(It->getValue()),
- SourceDag->getArg(I)))
- PrintFatalError(Rec->getLoc(),
- "Input Operand '" + SourceDag->getArgNameStr(I) +
- "' has a mismatched tied operand!\n");
- }
- It = DestOperands.find(SourceDag->getArgNameStr(I));
+ auto It = DestOperands.find(ArgName);
if (It == DestOperands.end())
- PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(I) +
+ PrintFatalError(Rec->getLoc(), "Operand " + ArgName +
" defined in Input Dag but not used in"
- " Output Dag!\n");
+ " Output Dag!");
// Input Dag operand types must match output Dag operand type.
- if (!validateArgsTypes(DestDag->getArg(It->getValue()),
+ if (!validateArgsTypes(DestDag->getArg(It->getValue().DAGOpNo),
SourceDag->getArg(I)))
PrintFatalError(Rec->getLoc(), "Type mismatch between Input and "
"Output Dag operand '" +
- SourceDag->getArgNameStr(I) + "'!");
- SourceOperands[SourceDag->getArgNameStr(I)] = I;
+ ArgName + "'!");
}
}
@@ -394,8 +387,7 @@ void CompressInstEmitter::createDagOperandMapping(
void CompressInstEmitter::createInstOperandMapping(
const Record *Rec, const DagInit *SourceDag, const DagInit *DestDag,
IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap,
- StringMap<unsigned> &SourceOperands, const CodeGenInstruction &DestInst,
- unsigned SourceLastTiedOp) {
+ StringMap<ArgData> &SourceOperands, const CodeGenInstruction &DestInst) {
// TiedCount keeps track of the number of operands skipped in Inst
// operands list to get to the corresponding Dag operand.
unsigned TiedCount = 0;
@@ -425,29 +417,21 @@ void CompressInstEmitter::createInstOperandMapping(
continue;
unsigned DagArgIdx = OpNo - TiedCount;
- StringMap<unsigned>::iterator SourceOp =
- SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
+ StringRef ArgName = DestDag->getArgNameStr(DagArgIdx);
+ auto SourceOp = SourceOperands.find(ArgName);
if (SourceOp == SourceOperands.end())
PrintFatalError(Rec->getLoc(),
- "Output Dag operand '" +
- DestDag->getArgNameStr(DagArgIdx) +
+ "Output Dag operand '" + ArgName +
"' has no matching input Dag operand.");
- assert(DestDag->getArgNameStr(DagArgIdx) ==
- SourceDag->getArgNameStr(SourceOp->getValue()) &&
+ assert(ArgName ==
+ SourceDag->getArgNameStr(SourceOp->getValue().DAGOpNo) &&
"Incorrect operand mapping detected!\n");
- // Following four lines ensure the correct handling of a single tied
- // operand in the Source Inst. SourceDagOp points to the position of
- // appropriate Dag argument which is not correct in presence of tied
- // operand in the Source Inst and must be incremented by 1 to reflect
- // correct position of the operand in Source Inst
- unsigned SourceDagOp = SourceOp->getValue();
- if (SourceDagOp >= SourceLastTiedOp)
- SourceDagOp++;
- DestOperandMap[OpNo].Data.Operand = SourceDagOp;
- SourceOperandMap[SourceDagOp].Data.Operand = OpNo;
- LLVM_DEBUG(dbgs() << " " << SourceDagOp << " ====> " << OpNo << "\n");
+ unsigned SourceOpNo = SourceOp->getValue().MIOpNo;
+ DestOperandMap[OpNo].Data.Operand = SourceOpNo;
+ SourceOperandMap[SourceOpNo].Data.Operand = OpNo;
+ LLVM_DEBUG(dbgs() << " " << SourceOpNo << " ====> " << OpNo << "\n");
}
}
}
@@ -506,27 +490,24 @@ void CompressInstEmitter::evaluateCompressPat(const Record *Rec) {
// Fill the mapping from the source to destination instructions.
IndexedMap<OpData> SourceOperandMap;
- unsigned SourceLastTiedOp; // postion of the last tied operand in Source Inst
+ // Map from arg name to DAG operand number and MI operand number.
+ StringMap<ArgData> SourceOperands;
// Create a mapping between source Dag operands and source Inst operands.
addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap,
- /*IsSourceInst*/ true, &SourceLastTiedOp);
+ SourceOperands, /*IsSourceInst*/ true);
IndexedMap<OpData> DestOperandMap;
+ // Map from arg name to DAG operand number and MI operand number.
+ StringMap<ArgData> DestOperands;
// Create a mapping between destination Dag operands and destination Inst
// operands.
- addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap,
- /*IsSourceInst*/ false, nullptr);
-
- StringMap<unsigned> SourceOperands;
- StringMap<unsigned> DestOperands;
- bool HasSourceTiedOp =
- SourceLastTiedOp != std::numeric_limits<unsigned int>::max();
- createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag,
- SourceOperandMap, HasSourceTiedOp);
+ addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, DestOperands,
+ /*IsSourceInst*/ false);
+
+ checkDagOperandMapping(Rec, DestOperands, SourceDag, DestDag);
// Create operand mapping between the source and destination instructions.
createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap,
- DestOperandMap, SourceOperands, DestInst,
- SourceLastTiedOp);
+ DestOperandMap, SourceOperands, DestInst);
// Get the target features for the CompressPat.
std::vector<const Record *> PatReqFeatures;
@@ -624,7 +605,7 @@ void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS,
if (!AsmWriter->getValueAsInt("PassSubtarget"))
PrintFatalError(AsmWriter->getLoc(),
"'PassSubtarget' is false. SubTargetInfo object is needed "
- "for target features.\n");
+ "for target features.");
StringRef TargetName = Target.getName();
@@ -780,7 +761,7 @@ void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS,
<< ").getReg() == MI.getOperand("
<< SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n";
else
- PrintFatalError("Unexpected tied operand types!\n");
+ PrintFatalError("Unexpected tied operand types!");
}
for (unsigned SubOp = 0; SubOp != SourceOperand.MINumOperands; ++SubOp) {
// Check for fixed immediates\registers in the source instruction.
More information about the llvm-commits
mailing list