Skip to content

Commit cbf6f65

Browse files
committed
[LLVM][TableGen] Support type casts of nodes with multiple results
Currently, type casts can only be used to pattern match for intrinsics with a single overloaded return value. For instance: ``` def int_foo : Intrinsic<[llvm_anyint_ty], []>; def : Pat<(i32 (int_foo)), ...>; ``` This patch extends type casts to support matching intrinsics with multiple overloaded return values. As an example, the following defines a pattern that matches only if the overloaded intrinsic call returns an `i16` for the first result and an `i32` for the second result: ``` def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>; def : Pat<([i16, i32] (int_bar)), ...>; ```
1 parent 234193b commit cbf6f65

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

llvm/lib/TableGen/TGParser.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2866,11 +2866,13 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
28662866

28672867
return ListInit::get(Vals, DeducedEltTy);
28682868
}
2869-
case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
2869+
case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
2870+
// Value ::= '(' '[' ValueList ']' DagArgList ')'
28702871
Lex.Lex(); // eat the '('
28712872
if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast &&
2872-
Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp) {
2873-
TokError("expected identifier in dag init");
2873+
Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp &&
2874+
Lex.getCode() != tgtok::l_square) {
2875+
TokError("expected identifier or list of value types in dag init");
28742876
return nullptr;
28752877
}
28762878

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s | FileCheck %s
2+
3+
include "llvm/Target/Target.td"
4+
5+
def TestTargetInstrInfo : InstrInfo;
6+
7+
def TestTarget : Target {
8+
let InstructionSet = TestTargetInstrInfo;
9+
}
10+
11+
def REG : Register<"REG">;
12+
def GPR : RegisterClass<"TestTarget", [i16, i32], 32, (add REG)>;
13+
14+
def int_foo : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
15+
16+
def INSTR_FOO_I16_I32 : Instruction {
17+
let OutOperandList = (outs GPR:$a, GPR:$b);
18+
let InOperandList = (ins);
19+
}
20+
21+
def INSTR_FOO_I32_I16 : Instruction {
22+
let OutOperandList = (outs GPR:$a, GPR:$b);
23+
let InOperandList = (ins);
24+
}
25+
26+
// CHECK: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN)
27+
// CHECK: 7*/ OPC_SwitchType {{.*}}, 10, /*MVT::i16*/6
28+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i32*/7
29+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I16_I32)
30+
def : Pat<([i16, i32] (int_foo)), ([i16, i32] (INSTR_FOO_I16_I32))>;
31+
32+
// CHECK: 20*/ /*SwitchType*/ {{.*}} /*MVT::i32*/7
33+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i16*/6
34+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I32_I16)
35+
def : Pat<([i32, i16] (int_foo)), ([i32, i16] (INSTR_FOO_I32_I16))>;

llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2886,6 +2886,35 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
28862886
error("Pattern has unexpected init kind!");
28872887
return nullptr;
28882888
}
2889+
2890+
auto ParseCastOperand = [this](DagInit *Dag, StringRef OpName) {
2891+
if (Dag->getNumArgs() != 1)
2892+
error("Type cast only takes one operand!");
2893+
2894+
if (!OpName.empty())
2895+
error("Type cast should not have a name!");
2896+
2897+
return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
2898+
};
2899+
2900+
if (ListInit *LI = dyn_cast<ListInit>(Dag->getOperator())) {
2901+
// If the operator is a list (of value types), then this must be "type cast"
2902+
// of a leaf node with multiple results.
2903+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
2904+
2905+
unsigned NumTypes = New->getNumTypes();
2906+
if (NumTypes != LI->size())
2907+
error("Invalid number of type casts!");
2908+
2909+
// Apply the type casts.
2910+
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
2911+
for (unsigned i = 0; i < NumTypes; ++i)
2912+
New->UpdateNodeType(
2913+
i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this);
2914+
2915+
return New;
2916+
}
2917+
28892918
DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
28902919
if (!OpDef) {
28912920
error("Pattern has unexpected operator type!");
@@ -2896,20 +2925,15 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
28962925
if (Operator->isSubClassOf("ValueType")) {
28972926
// If the operator is a ValueType, then this must be "type cast" of a leaf
28982927
// node.
2899-
if (Dag->getNumArgs() != 1)
2900-
error("Type cast only takes one operand!");
2928+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
29012929

2902-
TreePatternNodePtr New =
2903-
ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
2930+
if (New->getNumTypes() != 1)
2931+
error("ValueType cast can only have one type!");
29042932

29052933
// Apply the type cast.
2906-
if (New->getNumTypes() != 1)
2907-
error("Type cast can only have one type!");
29082934
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
29092935
New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
29102936

2911-
if (!OpName.empty())
2912-
error("ValueType cast should not have a name!");
29132937
return New;
29142938
}
29152939

0 commit comments

Comments
 (0)