[llvm] [TableGen] More generically handle tied source operands in CompressInstEmitter. (PR #146183)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 27 18:06:26 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-tablegen
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/146183.diff
1 Files Affected:
- (modified) llvm/utils/TableGen/CompressInstEmitter.cpp (+69-89)
``````````diff
diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp
index d3e98b3096afe..3758814d7c07b 100644
--- a/llvm/utils/TableGen/CompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/CompressInstEmitter.cpp
@@ -126,27 +126,24 @@ 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<std::pair<unsigned, unsigned>> &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 createInstOperandMapping(const Record *Rec, const DagInit *SourceDag,
- const DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap,
- IndexedMap<OpData> &DestOperandMap,
- StringMap<unsigned> &SourceOperands,
- const CodeGenInstruction &DestInst,
- unsigned SourceLastTiedOp);
+ void checkDagOperandMapping(
+ const Record *Rec,
+ const StringMap<std::pair<unsigned, unsigned>> &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<std::pair<unsigned, unsigned>> &SourceOperands,
+ const CodeGenInstruction &DestInst);
public:
CompressInstEmitter(const RecordKeeper &R) : Records(R), Target(R) {}
@@ -198,6 +195,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 different 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
@@ -205,12 +206,10 @@ bool CompressInstEmitter::validateTypes(const Record *DagOpType,
/// operands and fixed registers it expects the Dag operand type to be contained
/// in the instantiated instruction operand type. For immediate operands and
/// immediates no validation checks are enforced at pattern validation time.
-void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
- const DagInit *Dag,
- const CodeGenInstruction &Inst,
- IndexedMap<OpData> &OperandMap,
- bool IsSourceInst,
- unsigned *SourceLastTiedOpPtr) {
+void CompressInstEmitter::addDagOperandMapping(
+ const Record *Rec, const DagInit *Dag, const CodeGenInstruction &Inst,
+ IndexedMap<OpData> &OperandMap,
+ StringMap<std::pair<unsigned, unsigned>> &Operands, bool IsSourceInst) {
unsigned NumMIOperands = 0;
if (!Inst.Operands.empty())
NumMIOperands =
@@ -224,16 +223,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 +285,28 @@ 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 (tied) same Dag we use the last occurrence for indexing.
+ if (Dag->getArgNameStr(DAGOpNo).empty())
+ continue;
+
+ if (IsSourceInst) {
+ auto It = Operands.find(Dag->getArgNameStr(DAGOpNo));
+ if (It != Operands.end()) {
+ OperandMap[OpNo].TiedOpIdx = It->getValue().second;
+ if (!validateArgsTypes(Dag->getArg(It->getValue().first),
+ Dag->getArg(DAGOpNo)))
+ PrintFatalError(Rec->getLoc(),
+ "Input Operand '" + Dag->getArgNameStr(DAGOpNo) +
+ "' has a mismatched tied operand!\n");
+ }
+ }
+
+ Operands[Dag->getArgNameStr(DAGOpNo)] = {DAGOpNo, OpNo};
}
}
}
@@ -331,60 +348,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<std::pair<unsigned, unsigned>> &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))
+ if (SourceDag->getArgNameStr(I).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(SourceDag->getArgNameStr(I));
if (It == DestOperands.end())
PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(I) +
" defined in Input Dag but not used in"
" Output Dag!\n");
// Input Dag operand types must match output Dag operand type.
- if (!validateArgsTypes(DestDag->getArg(It->getValue()),
+ if (!validateArgsTypes(DestDag->getArg(It->getValue().first),
SourceDag->getArg(I)))
PrintFatalError(Rec->getLoc(), "Type mismatch between Input and "
"Output Dag operand '" +
SourceDag->getArgNameStr(I) + "'!");
- SourceOperands[SourceDag->getArgNameStr(I)] = I;
}
}
@@ -394,8 +380,8 @@ 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<std::pair<unsigned, unsigned>> &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,8 +411,7 @@ void CompressInstEmitter::createInstOperandMapping(
continue;
unsigned DagArgIdx = OpNo - TiedCount;
- StringMap<unsigned>::iterator SourceOp =
- SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
+ auto SourceOp = SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
if (SourceOp == SourceOperands.end())
PrintFatalError(Rec->getLoc(),
"Output Dag operand '" +
@@ -434,7 +419,7 @@ void CompressInstEmitter::createInstOperandMapping(
"' has no matching input Dag operand.");
assert(DestDag->getArgNameStr(DagArgIdx) ==
- SourceDag->getArgNameStr(SourceOp->getValue()) &&
+ SourceDag->getArgNameStr(SourceOp->getValue().first) &&
"Incorrect operand mapping detected!\n");
// Following four lines ensure the correct handling of a single tied
@@ -442,12 +427,10 @@ void CompressInstEmitter::createInstOperandMapping(
// 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().second;
+ DestOperandMap[OpNo].Data.Operand = SourceOpNo;
+ SourceOperandMap[SourceOpNo].Data.Operand = OpNo;
+ LLVM_DEBUG(dbgs() << " " << SourceOpNo << " ====> " << OpNo << "\n");
}
}
}
@@ -506,27 +489,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<std::pair<unsigned, unsigned>> 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<std::pair<unsigned, unsigned>> 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;
``````````
</details>
https://github.com/llvm/llvm-project/pull/146183
More information about the llvm-commits
mailing list