Skip to content

Commit ee9c4ce

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 8b4b7d2 commit ee9c4ce

File tree

4 files changed

+100
-11
lines changed

4 files changed

+100
-11
lines changed

llvm/lib/TableGen/TGParser.cpp

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

28452845
return ListInit::get(Vals, DeducedEltTy);
28462846
}
2847-
case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
2847+
case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
2848+
// Value ::= '(' '[' ValueList ']' DagArgList ')'
28482849
Lex.Lex(); // eat the '('
28492850
if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast &&
2850-
Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp) {
2851-
TokError("expected identifier in dag init");
2851+
Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp &&
2852+
Lex.getCode() != tgtok::l_square) {
2853+
TokError("expected identifier or list of value types in dag init");
28522854
return nullptr;
28532855
}
28542856

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false -warn-on-skipped-patterns -I %p/../../include -I %p/Common %s -o - < %s | FileCheck %s
2+
3+
include "llvm/Target/Target.td"
4+
include "GlobalISelEmitterCommon.td"
5+
6+
def REG : Register<"REG">;
7+
def GPR : RegisterClass<"MyTarget", [i16, i32], 32, (add REG)>;
8+
9+
def int_foo : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
10+
11+
def INSTR_FOO_I16_I32 : Instruction {
12+
let OutOperandList = (outs GPR:$a, GPR:$b);
13+
let InOperandList = (ins);
14+
}
15+
16+
def INSTR_FOO_I32_I16 : Instruction {
17+
let OutOperandList = (outs GPR:$a, GPR:$b);
18+
let InOperandList = (ins);
19+
}
20+
21+
// CHECK: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s16
22+
// CHECK: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_s32
23+
// CHECK: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(::INSTR_FOO_I16_I32)
24+
def : Pat<([i16, i32] (int_foo)), ([i16, i32] (INSTR_FOO_I16_I32))>;
25+
26+
// CHECK: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s32
27+
// CHECK: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_s16
28+
// CHECK: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(::INSTR_FOO_I32_I16)
29+
def : Pat<([i32, i16] (int_foo)), ([i32, i16] (INSTR_FOO_I32_I16))>;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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: 7*/ OPC_SwitchType {{.*}}, 10, /*MVT::i16*/6
27+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i32*/7
28+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I16_I32)
29+
def : Pat<([i16, i32] (int_foo)), ([i16, i32] (INSTR_FOO_I16_I32))>;
30+
31+
// CHECK: 20*/ /*SwitchType*/ {{.*}} /*MVT::i32*/7
32+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i16*/6
33+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I32_I16)
34+
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
@@ -2896,6 +2896,35 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
28962896
error("Pattern has unexpected init kind!");
28972897
return nullptr;
28982898
}
2899+
2900+
auto ParseCastOperand = [this](DagInit *Dag, StringRef OpName) {
2901+
if (Dag->getNumArgs() != 1)
2902+
error("Type cast only takes one operand!");
2903+
2904+
if (!OpName.empty())
2905+
error("Type cast should not have a name!");
2906+
2907+
return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
2908+
};
2909+
2910+
if (ListInit *LI = dyn_cast<ListInit>(Dag->getOperator())) {
2911+
// If the operator is a list (of value types), then this must be "type cast"
2912+
// of a leaf node with multiple results.
2913+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
2914+
2915+
unsigned NumTypes = New->getNumTypes();
2916+
if (NumTypes != LI->size())
2917+
error("Invalid number of type casts!");
2918+
2919+
// Apply the type casts.
2920+
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
2921+
for (unsigned i = 0; i < NumTypes; ++i)
2922+
New->UpdateNodeType(
2923+
i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this);
2924+
2925+
return New;
2926+
}
2927+
28992928
DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
29002929
if (!OpDef) {
29012930
error("Pattern has unexpected operator type!");
@@ -2906,20 +2935,15 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
29062935
if (Operator->isSubClassOf("ValueType")) {
29072936
// If the operator is a ValueType, then this must be "type cast" of a leaf
29082937
// node.
2909-
if (Dag->getNumArgs() != 1)
2910-
error("Type cast only takes one operand!");
2938+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
29112939

2912-
TreePatternNodePtr New =
2913-
ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
2940+
if (New->getNumTypes() != 1)
2941+
error("ValueType cast can only have one type!");
29142942

29152943
// Apply the type cast.
2916-
if (New->getNumTypes() != 1)
2917-
error("Type cast can only have one type!");
29182944
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
29192945
New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
29202946

2921-
if (!OpName.empty())
2922-
error("ValueType cast should not have a name!");
29232947
return New;
29242948
}
29252949

0 commit comments

Comments
 (0)