[llvm] f672f32 - [TableGen] Improve error message for bad VTByHwMode in RegisterByHwMode
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 10 13:59:42 PST 2025
Author: Alexander Richardson
Date: 2025-12-10T13:59:38-08:00
New Revision: f672f32fa24aec5f440827b5beedcb6627769fcf
URL: https://github.com/llvm/llvm-project/commit/f672f32fa24aec5f440827b5beedcb6627769fcf
DIFF: https://github.com/llvm/llvm-project/commit/f672f32fa24aec5f440827b5beedcb6627769fcf.diff
LOG: [TableGen] Improve error message for bad VTByHwMode in RegisterByHwMode
Previously we would assert when a ValueTypeByHwMode was missing a case
for the current mode, now we report an error instead. Interestingly this
error only ocurrs when the DAG patterns use RegClassByHwMode, but not
normal RegisterClass instances. Found while I added RegClassByHwMode
to RISC-V and was getting an assertion due to `XLenFVT`/`XLenVecI32VT`
not having an entry for the default mode.
Reviewed By: arsenm
Pull Request: https://github.com/llvm/llvm-project/pull/171254
Added:
Modified:
llvm/test/TableGen/RegClassByHwModeErrors.td
llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
llvm/utils/TableGen/Common/InfoByHwMode.cpp
llvm/utils/TableGen/Common/InfoByHwMode.h
Removed:
################################################################################
diff --git a/llvm/test/TableGen/RegClassByHwModeErrors.td b/llvm/test/TableGen/RegClassByHwModeErrors.td
index 5d91b6e70410b..0ee6370ccd0ce 100644
--- a/llvm/test/TableGen/RegClassByHwModeErrors.td
+++ b/llvm/test/TableGen/RegClassByHwModeErrors.td
@@ -7,6 +7,8 @@
// RUN: %t/compress-regclass-by-hwmode.td -o /dev/null 2>&1 | FileCheck %t/compress-regclass-by-hwmode.td --implicit-check-not="error:"
// RUN: not llvm-tblgen --gen-compress-inst-emitter -I %p/../../include -I %t -I %S \
// RUN: %t/compress-regclass-by-hwmode-2.td -o /dev/null 2>&1 | FileCheck %t/compress-regclass-by-hwmode-2.td --implicit-check-not="error:"
+// RUN: not llvm-tblgen --gen-dag-isel -I %p/../../include -I %t -I %S \
+// RUN: %t/vt-by-hwmode-missing.td -o /dev/null 2>&1 | FileCheck %t/vt-by-hwmode-missing.td --implicit-check-not="error:"
//--- Common.td
include "Common/RegClassByHwModeCommon.td"
@@ -86,3 +88,34 @@ def : CompressPat<(X_MOV_BIG XRegs:$dst, XRegs:$src),
// CHECK: [[#@LINE-2]]:1: error: Type mismatch between Input and Output Dag operand 'dst'
def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }
+
+
+//--- vt-by-hwmode-missing.td
+include "Common.td"
+/// This should fail since we are missing a DefaultMode entry for the
+/// ValueTypeByHwMode and can't resolve it for the Ptr32 (default) case.
+def BadVT : ValueTypeByHwMode<[Ptr64], [i64]>;
+def BadVTRegClass : RegisterClass<"MyTarget", [i64, BadVT], 64, (add Y0, Y1)>;
+/// NOTE: this error only occurs for RegClassByHwMode, normal RegisterClass
+/// logic for VT resolution takes a
diff erent code path and does not error.
+def TEST_OK : TestInstruction {
+ let OutOperandList = (outs BadVTRegClass:$dst);
+ let InOperandList = (ins BadVTRegClass:$src1, BadVTRegClass:$src2);
+ let AsmString = "test $dst, $src1, $src2";
+ let Pattern = [(set BadVTRegClass:$dst, (add BadVTRegClass:$src1, BadVTRegClass:$src2))];
+}
+/// Once we use RegClassByHwMode, we get an error about missing modes:
+def BadPtrRC : RegClassByHwMode<[Ptr32, Ptr64], [BadVTRegClass, YRegs]>;
+// CHECK: vt-by-hwmode-missing.td:[[#@LINE-1]]:5: error: Could not resolve VT for Mode DefaultMode
+// CHECK: vt-by-hwmode-missing.td:4:5: note: ValueTypeByHwMode BadVT defined here
+// CHECK: vt-by-hwmode-missing.td:[[#@LINE+1]]:5: note: pattern instantiated here
+def TEST : TestInstruction {
+ let OutOperandList = (outs BadPtrRC:$dst);
+ let InOperandList = (ins BadPtrRC:$src1, BadPtrRC:$src2);
+ let AsmString = "test $dst, $src1, $src2";
+ let opcode = 0;
+ let Pattern = [(set BadPtrRC:$dst, (add BadPtrRC:$src1, BadPtrRC:$src2))];
+}
+
+def MyTargetISA : InstrInfo;
+def MyTarget : Target { let InstructionSet = MyTargetISA; }
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index 364817fa6d030..61c5a9f138bfa 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -1798,15 +1798,27 @@ bool llvm::operator<(const SDTypeConstraint &LHS, const SDTypeConstraint &RHS) {
/// RegClassByHwMode acts like ValueTypeByHwMode, taking the type of the
/// register class from the active mode.
static TypeSetByHwMode getTypeForRegClassByHwMode(const CodeGenTarget &T,
- const Record *R) {
+ const Record *R,
+ ArrayRef<SMLoc> Loc) {
TypeSetByHwMode TypeSet;
RegClassByHwMode Helper(R, T.getHwModes(), T.getRegBank());
for (auto [ModeID, RegClass] : Helper) {
ArrayRef<ValueTypeByHwMode> RegClassVTs = RegClass->getValueTypes();
MachineValueTypeSet &ModeTypeSet = TypeSet.getOrCreate(ModeID);
- for (const ValueTypeByHwMode &VT : RegClassVTs)
+ for (const ValueTypeByHwMode &VT : RegClassVTs) {
+ if (!VT.hasMode(ModeID) && !VT.hasDefault()) {
+ PrintError(R->getLoc(), "Could not resolve VT for Mode " +
+ T.getHwModes().getModeName(ModeID, true));
+ if (VT.getRecord())
+ PrintNote(VT.getRecord()->getLoc(), "ValueTypeByHwMode " +
+ VT.getRecord()->getName() +
+ " defined here");
+ PrintFatalNote(Loc, "pattern instantiated here");
+ continue;
+ }
ModeTypeSet.insert(VT.getType(ModeID));
+ }
}
return TypeSet;
@@ -1841,7 +1853,9 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
assert(RC && "Unknown operand type");
CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();
if (RC->isSubClassOf("RegClassByHwMode"))
- return UpdateNodeType(ResNo, getTypeForRegClassByHwMode(Tgt, RC), TP);
+ return UpdateNodeType(
+ ResNo, getTypeForRegClassByHwMode(Tgt, RC, TP.getRecord()->getLoc()),
+ TP);
return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);
}
@@ -2331,7 +2345,7 @@ static TypeSetByHwMode getImplicitType(const Record *R, unsigned ResNo,
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
if (RegClass->isSubClassOf("RegClassByHwMode"))
- return getTypeForRegClassByHwMode(T, RegClass);
+ return getTypeForRegClassByHwMode(T, RegClass, TP.getRecord()->getLoc());
return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes());
}
@@ -2354,7 +2368,7 @@ static TypeSetByHwMode getImplicitType(const Record *R, unsigned ResNo,
if (R->isSubClassOf("RegClassByHwMode")) {
const CodeGenTarget &T = CDP.getTargetInfo();
- return getTypeForRegClassByHwMode(T, R);
+ return getTypeForRegClassByHwMode(T, R, TP.getRecord()->getLoc());
}
if (R->isSubClassOf("PatFrags")) {
diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.cpp b/llvm/utils/TableGen/Common/InfoByHwMode.cpp
index a16fdbb58e788..a3f8909c36090 100644
--- a/llvm/utils/TableGen/Common/InfoByHwMode.cpp
+++ b/llvm/utils/TableGen/Common/InfoByHwMode.cpp
@@ -29,8 +29,8 @@ std::string llvm::getModeName(unsigned Mode) {
return (Twine('m') + Twine(Mode)).str();
}
-ValueTypeByHwMode::ValueTypeByHwMode(const Record *R,
- const CodeGenHwModes &CGH) {
+ValueTypeByHwMode::ValueTypeByHwMode(const Record *R, const CodeGenHwModes &CGH)
+ : InfoByHwMode<llvm::MVT>(R) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.try_emplace(P.first, MVT(llvm::getValueType(P.second)));
@@ -140,7 +140,8 @@ void RegSizeInfo::writeToStream(raw_ostream &OS) const {
}
RegSizeInfoByHwMode::RegSizeInfoByHwMode(const Record *R,
- const CodeGenHwModes &CGH) {
+ const CodeGenHwModes &CGH)
+ : InfoByHwMode<llvm::RegSizeInfo>(R) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.try_emplace(P.first, RegSizeInfo(P.second));
@@ -188,7 +189,8 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
}
RegClassByHwMode::RegClassByHwMode(const Record *R, const CodeGenHwModes &CGH,
- const CodeGenRegBank &RegBank) {
+ const CodeGenRegBank &RegBank)
+ : InfoByHwMode<const llvm::CodeGenRegisterClass *>(R) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (auto [ModeID, RegClassRec] : MS.Items) {
@@ -206,7 +208,8 @@ SubRegRange::SubRegRange(const Record *R) {
}
SubRegRangeByHwMode::SubRegRangeByHwMode(const Record *R,
- const CodeGenHwModes &CGH) {
+ const CodeGenHwModes &CGH)
+ : InfoByHwMode<llvm::SubRegRange>(R) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.try_emplace(P.first, SubRegRange(P.second));
@@ -216,7 +219,8 @@ SubRegRangeByHwMode::SubRegRangeByHwMode(const Record *R,
}
EncodingInfoByHwMode::EncodingInfoByHwMode(const Record *R,
- const CodeGenHwModes &CGH) {
+ const CodeGenHwModes &CGH)
+ : InfoByHwMode<const llvm::Record *>(R) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
assert(P.second && P.second->isSubClassOf("InstructionEncoding") &&
diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.h b/llvm/utils/TableGen/Common/InfoByHwMode.h
index bd24fb84b085a..d53a218a40512 100644
--- a/llvm/utils/TableGen/Common/InfoByHwMode.h
+++ b/llvm/utils/TableGen/Common/InfoByHwMode.h
@@ -91,7 +91,7 @@ template <typename InfoT> struct InfoByHwMode {
using iterator = typename MapType::iterator;
using const_iterator = typename MapType::const_iterator;
- InfoByHwMode() = default;
+ explicit InfoByHwMode(const Record *Def = nullptr) : Def(Def) {};
InfoByHwMode(const MapType &M) : Map(M) {}
LLVM_ATTRIBUTE_ALWAYS_INLINE
@@ -150,8 +150,11 @@ template <typename InfoT> struct InfoByHwMode {
Map.try_emplace(DefaultMode, I);
}
+ const Record *getRecord() const { return Def; }
+
protected:
MapType Map;
+ const Record *Def;
};
struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
More information about the llvm-commits
mailing list