[llvm] [RFC][TableGen] Require DAG argument for complex operands in InstAlias (PR #136411)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 23 09:59:18 PDT 2025


================
@@ -15,155 +15,125 @@
 #include "CodeGenRegisters.h"
 #include "CodeGenTarget.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Error.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
 
 using namespace llvm;
 
-/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
-/// constructor.  It checks if an argument in an InstAlias pattern matches
-/// the corresponding operand of the instruction.  It returns true on a
-/// successful match, with ResOp set to the result operand to be used.
-bool CodeGenInstAlias::tryAliasOpMatch(const DagInit *Result,
-                                       unsigned AliasOpNo,
-                                       const Record *InstOpRec, bool hasSubOps,
-                                       ArrayRef<SMLoc> Loc,
-                                       const CodeGenTarget &T,
-                                       ResultOperand &ResOp) {
-  const Init *Arg = Result->getArg(AliasOpNo);
-  const DefInit *ADI = dyn_cast<DefInit>(Arg);
-  const Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
-
-  if (ADI && ADI->getDef() == InstOpRec) {
-    // If the operand is a record, it must have a name, and the record type
-    // must match up with the instruction's argument type.
-    if (!Result->getArgName(AliasOpNo))
-      PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
-                               " must have a name!");
-    ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
-                          ResultRecord);
-    return true;
-  }
-
-  // For register operands, the source register class can be a subclass
-  // of the instruction register class, not just an exact match.
-  if (InstOpRec->isSubClassOf("RegisterOperand"))
-    InstOpRec = InstOpRec->getValueAsDef("RegClass");
+unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
+  if (!isRecord())
+    return 1;
 
-  if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
-    ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
+  const Record *Rec = getRecord();
+  if (!Rec->isSubClassOf("Operand"))
+    return 1;
 
-  if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
-    if (!InstOpRec->isSubClassOf("RegisterClass"))
-      return false;
-    if (!T.getRegisterClass(InstOpRec).hasSubClass(
-            &T.getRegisterClass(ADI->getDef())))
-      return false;
-    ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
-                          ResultRecord);
-    return true;
+  const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
+  if (MIOpInfo->getNumArgs() == 0) {
+    // Unspecified, so it defaults to 1
+    return 1;
   }
 
-  // Handle explicit registers.
-  if (ADI && ADI->getDef()->isSubClassOf("Register")) {
-    if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
-      const DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
-      // The operand info should only have a single (register) entry. We
-      // want the register class of it.
-      InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
-    }
-
-    if (!InstOpRec->isSubClassOf("RegisterClass"))
-      return false;
-
-    if (!T.getRegisterClass(InstOpRec).contains(
-            T.getRegBank().getReg(ADI->getDef())))
-      PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
-                               " is not a member of the " +
-                               InstOpRec->getName() + " register class!");
-
-    if (Result->getArgName(AliasOpNo))
-      PrintFatalError(Loc, "result fixed register argument must "
-                           "not have a name!");
+  return MIOpInfo->getNumArgs();
+}
 
-    ResOp = ResultOperand(ResultRecord);
-    return true;
+static const Record *getInitValueAsRegClass(const Init *V) {
+  if (const DefInit *VDefInit = dyn_cast<DefInit>(V)) {
+    const Record *R = VDefInit->getDef();
+    if (R->isSubClassOf("RegisterClass"))
+      return R;
+    if (R->isSubClassOf("RegisterOperand"))
+      return R->getValueAsDef("RegClass");
   }
+  return nullptr;
+}
+
+using ResultOperand = CodeGenInstAlias::ResultOperand;
+
+static Expected<ResultOperand> matchSimpleOperand(const Init *Arg,
+                                                  const StringInit *ArgName,
+                                                  const Record *Op,
+                                                  const CodeGenTarget &T) {
+  if (Op->isSubClassOf("RegisterClass") ||
+      Op->isSubClassOf("RegisterOperand")) {
+    const Record *OpRC =
+        Op->isSubClassOf("RegisterClass") ? Op : Op->getValueAsDef("RegClass");
+
+    if (const auto *ArgDef = dyn_cast<DefInit>(Arg)) {
+      const Record *ArgRec = ArgDef->getDef();
+
+      // Match 'RegClass:$name' or 'RegOp:$name'.
+      if (const Record *ArgRC = getInitValueAsRegClass(Arg)) {
+        if (!T.getRegisterClass(OpRC).hasSubClass(&T.getRegisterClass(ArgRC)))
+          return createStringError(
+              "argument register class" + ArgRC->getName() +
+              " is not a subclass of operand register class " +
+              OpRC->getName());
+        if (!ArgName)
+          return createStringError("register class argument must have a name");
+        return ResultOperand::createRecord(ArgName->getAsUnquotedString(),
+                                           cast<DefInit>(Arg)->getDef());
----------------
paulwalker-arm wrote:

Can this be?
```suggestion
        return ResultOperand::createRecord(ArgName->getAsUnquotedString(), ArgRec);
```

https://github.com/llvm/llvm-project/pull/136411


More information about the llvm-commits mailing list