Skip to content

Commit 65f0c3a

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 example: ``` 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. This is enabled with a new `ValueTypeList` class that can be used to define the target of a type cast. As an example, the following defines a pattern that matches only if the results of the overloaded intrinsic call are both `i32`: ``` def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>; def i32_i32 : ValueTypeList<[i32, i32]>; def : Pat<(i32_i32 (int_bar)), ...>; ```
1 parent 42b696d commit 65f0c3a

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,3 +2070,18 @@ class ComplexPattern<ValueType ty, int numops, string fn,
20702070
list<SDNodeProperty> Properties = props;
20712071
int Complexity = complexity;
20722072
}
2073+
2074+
//===----------------------------------------------------------------------===//
2075+
// Value type list.
2076+
//
2077+
// This can be used to pattern match for intrinsics with multiple overloaded
2078+
// return values. For example:
2079+
//
2080+
// def int_foo : Irtrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
2081+
// def i32_i32 : ValueTypeList<[i32, i32]>;
2082+
// def : Pat<(i32_i32 (int_foo)), ...>;
2083+
//
2084+
2085+
class ValueTypeList<list<ValueType> vts> {
2086+
list<ValueType> VTs = vts ;
2087+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
def i16_i32 : ValueTypeList<[i16, i32]>;
27+
def i32_i16 : ValueTypeList<[i32, i16]>;
28+
29+
// CHECK: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN)
30+
// CHECK: 7*/ OPC_SwitchType {{.*}}, 10, /*MVT::i16*/6
31+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i32*/7
32+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I16_I32)
33+
def : Pat<(i16_i32 (int_foo)), (i16_i32 (INSTR_FOO_I16_I32))>;
34+
35+
// CHECK: 20*/ /*SwitchType*/ {{.*}} /*MVT::i32*/7
36+
// CHECK: OPC_CheckTypeRes, 1, /*MVT::i16*/6
37+
// CHECK: OPC_MorphNodeTo2Chain, TARGET_VAL(::INSTR_FOO_I32_I16)
38+
def : Pat<(i32_i16 (int_foo)), (i32_i16 (INSTR_FOO_I32_I16))>;

llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,23 +2903,46 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
29032903
}
29042904
Record *Operator = OpDef->getDef();
29052905

2906+
auto ParseCastOperand = [this](DagInit *Dag, StringRef OpName) {
2907+
if (Dag->getNumArgs() != 1)
2908+
error("Type cast only takes one operand!");
2909+
2910+
if (!OpName.empty())
2911+
error("Type cast should not have a name!");
2912+
2913+
return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
2914+
};
2915+
29062916
if (Operator->isSubClassOf("ValueType")) {
29072917
// If the operator is a ValueType, then this must be "type cast" of a leaf
29082918
// node.
2909-
if (Dag->getNumArgs() != 1)
2910-
error("Type cast only takes one operand!");
2919+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
29112920

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

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

2921-
if (!OpName.empty())
2922-
error("ValueType cast should not have a name!");
2928+
return New;
2929+
}
2930+
2931+
if (Operator->isSubClassOf("ValueTypeList")) {
2932+
// If the operator is a ValueTypeList, then this must be "type cast" of a
2933+
// leaf node with multiple results.
2934+
TreePatternNodePtr New = ParseCastOperand(Dag, OpName);
2935+
2936+
ListInit *LI = Operator->getValueAsListInit("VTs");
2937+
if (New->getNumTypes() != LI->size())
2938+
error("Invalid number of type casts!");
2939+
2940+
// Apply the type casts.
2941+
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
2942+
for (unsigned i = 0, e = New->getNumTypes(); i != e; ++i)
2943+
New->UpdateNodeType(
2944+
i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this);
2945+
29232946
return New;
29242947
}
29252948

0 commit comments

Comments
 (0)