[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