Skip to content

Commit 390c8ba

Browse files
committed
[gicombiner] Add the MatchDag structure and parse instruction DAG's from the input
Summary: The MatchDag structure is a representation of the checks that need to be performed and the dependencies that limit when they can happen. There are two kinds of node in the MatchDag: * Instrs - Represent a MachineInstr * Predicates - Represent a check that needs to be performed (i.e. opcode, is register, same machine operand, etc.) and two kinds of edges: * (Traversal) Edges - Represent a register that can be traversed to find one instr from another * Predicate Dependency Edges - Indicate that a predicate requires a piece of information to be tested. For example, the matcher: (match (MOV $t, $s), (MOV $d, $t)) with MOV declared as an instruction of the form: %dst = MOV %src1 becomes the following MatchDag with the following instruction nodes: __anon0_0 // $t=getOperand(0), $s=getOperand(1) __anon0_1 // $d=getOperand(0), $t=getOperand(1) traversal edges: __anon0_1[src1] --[t]--> __anon0_0[dst] predicate nodes: <<$mi.getOpcode() == MOV>>:$__anonpred0_2 <<$mi.getOpcode() == MOV>>:$__anonpred0_3 and predicate dependencies: __anon0_0 ==> __anonpred0_2[mi] __anon0_0 ==> __anonpred0_3[mi] The result of this parse is currently unused but can be tested using -gicombiner-stop-after-parse as done in parse-match-pattern.td. The dump for testing includes a graphviz format dump to allow the rule to be viewed visually. Later on, these MatchDag's will be used to generate code and to build an efficient decision tree. Reviewers: volkan, bogner Reviewed By: volkan Subscribers: arsenm, mgorny, mgrang, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D69077
1 parent 268f37d commit 390c8ba

16 files changed

+1492
-3
lines changed

llvm/test/TableGen/GICombinerEmitter/match-invalid.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ def unknown_kind2 : GICombineRule<
5353
// CHECK-NEXT: def unknown_kind2 : GICombineRule<
5454
// CHECK: :[[@LINE-6]]:{{[0-9]+}}: error: Failed to parse rule
5555

56+
def multidef : GICombineRule<
57+
(defs root:$a),
58+
(match (MOV $a, $b),
59+
(MOV $a, $b)),
60+
(dummy)>;
61+
// CHECK: :[[@LINE-5]]:{{[0-9]+}}: error: Two different MachineInstrs cannot def the same vreg
62+
// CHECK-NEXT: def multidef : GICombineRule<
63+
// CHECK: :[[@LINE-7]]:{{[0-9]+}}: error: Failed to parse rule
64+
5665
def multidef_but_not_an_error: GICombineRule<
5766
(defs root:$a),
5867
(match (MOV $a, $b),
@@ -66,6 +75,7 @@ def MyCombiner: GICombinerHelper<"GenMyCombiner", [
6675
null_matcher,
6776
unknown_kind1,
6877
unknown_kind2,
78+
multidef
6979
// Rules omitted from a matcher can be as broken as you like. They will not be read.
7080
// multidef_but_not_an_error
7181
]>;
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
2+
// RUN: -combiners=MyCombiner -gicombiner-stop-after-parse %s \
3+
// RUN: -o /dev/null -debug 2>&1 | FileCheck %s
4+
5+
include "llvm/Target/Target.td"
6+
include "llvm/Target/GlobalISel/Combine.td"
7+
8+
def MyTargetISA : InstrInfo;
9+
def MyTarget : Target { let InstructionSet = MyTargetISA; }
10+
11+
def dummy;
12+
13+
def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
14+
def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
15+
class I<dag OOps, dag IOps, list<dag> Pat>
16+
: Instruction {
17+
let Namespace = "MyTarget";
18+
let OutOperandList = OOps;
19+
let InOperandList = IOps;
20+
let Pattern = Pat;
21+
}
22+
def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1), []>;
23+
def MOV2 : I<(outs GPR32:$dst), (ins GPR32:$src1), []>;
24+
25+
def trivial : GICombineRule<
26+
(defs root:$d),
27+
(match (MOV $d, $s)),
28+
(apply [{ APPLY }])>;
29+
30+
// CHECK-LABEL: Parsed rule defs/match for 'trivial'
31+
32+
// The matchdag block is a fairly direct dump of the information that was read.
33+
// It's oriented towards the data structures within tablegen.
34+
// CHECK-NEXT: matchdag {
35+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon0_0 // $d=getOperand(0), $s=getOperand(1)
36+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred0_1
37+
// CHECK-NEXT: __anon0_0 ==> __anonpred0_1[mi]
38+
// CHECK-NEXT: {{^}$}}
39+
40+
// The digraph block is a human-oriented dump of the information that was read.
41+
// Run it through graphviz to produce a nice DAG showing the matcher behaviour.
42+
// CHECK-NEXT: digraph "trivial" {
43+
// CHECK-NEXT: rankdir="BT"
44+
// CHECK-NEXT: Node[[N1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon0_0|MOV|Match starts here|$d=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
45+
// CHECK-NEXT: Pred[[P1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred0_1|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
46+
// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
47+
// CHECK-NEXT: {{^}$}}
48+
49+
def simple : GICombineRule<
50+
(defs root:$d),
51+
(match (MOV $t, $s),
52+
(MOV $d, $t)),
53+
(apply [{ APPLY }])>;
54+
55+
// CHECK-LABEL: Parsed rule defs/match for 'simple'
56+
57+
// CHECK-NEXT: matchdag {
58+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon1_0 // $t=getOperand(0), $s=getOperand(1)
59+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon1_2 // $d=getOperand(0), $t=getOperand(1)
60+
// CHECK-NEXT: __anon1_2[src1] --[t]--> __anon1_0[dst]
61+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred1_1
62+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred1_3
63+
// CHECK-NEXT: __anon1_0 ==> __anonpred1_1[mi]
64+
// CHECK-NEXT: __anon1_2 ==> __anonpred1_3[mi]
65+
// CHECK-NEXT: {{^}$}}
66+
67+
// CHECK-NEXT: digraph "simple" {
68+
// CHECK-NEXT: rankdir="BT"
69+
// CHECK-NEXT: Node[[N1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon1_0|MOV|$t=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}"]
70+
// CHECK-NEXT: Node[[N2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon1_2|MOV|Match starts here|$d=getOperand(0), $t=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
71+
// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$t"]
72+
// CHECK-NEXT: Pred[[P1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred1_1|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
73+
// CHECK-NEXT: Pred[[P2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred1_3|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
74+
// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
75+
// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
76+
// CHECK-NEXT: {{^}$}}
77+
78+
def multiroot : GICombineRule<
79+
(defs root:$d1, root:$d2),
80+
(match (MOV $s, $s2),
81+
(MOV $d1, $s),
82+
(MOV $d2, $s)),
83+
(apply [{ APPLY }])>;
84+
85+
// CHECK-LABEL: Parsed rule defs/match for 'multiroot'
86+
87+
// CHECK-NEXT: matchdag {
88+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_0 // $s=getOperand(0), $s2=getOperand(1)
89+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_2 // $d1=getOperand(0), $s=getOperand(1)
90+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_4 // $d2=getOperand(0), $s=getOperand(1)
91+
// CHECK-NEXT: __anon2_2[src1] --[s]--> __anon2_0[dst]
92+
// CHECK-NEXT: __anon2_4[src1] --[s]--> __anon2_0[dst]
93+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_1
94+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_3
95+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_5
96+
// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred2_6
97+
// CHECK-NEXT: __anon2_0 ==> __anonpred2_1[mi]
98+
// CHECK-NEXT: __anon2_2 ==> __anonpred2_3[mi]
99+
// CHECK-NEXT: __anon2_4 ==> __anonpred2_5[mi]
100+
// CHECK-NEXT: __anon2_2[src1] ==> __anonpred2_6[mi0]
101+
// CHECK-NEXT: __anon2_4[src1] ==> __anonpred2_6[mi1]
102+
// CHECK-NEXT: {{^}$}}
103+
104+
// CHECK-NEXT: digraph "multiroot" {
105+
// CHECK-NEXT: rankdir="BT"
106+
// CHECK-NEXT: Node[[N1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon2_0|MOV|$s=getOperand(0), $s2=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}"]
107+
// CHECK-NEXT: Node[[N2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon2_2|MOV|Match starts here|$d1=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
108+
// CHECK-NEXT: Node[[N3:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon2_4|MOV|Match starts here|$d2=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
109+
// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
110+
// CHECK-NEXT: Node[[N3]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
111+
// CHECK-NEXT: Pred[[P1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred2_1|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
112+
// CHECK-NEXT: Pred[[P2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred2_3|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
113+
// CHECK-NEXT: Pred[[P3:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred2_5|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
114+
// CHECK-NEXT: Pred[[P4:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi0|<s2>#2 $mi1}|__anonpred2_6|$mi0 == $mi1|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi0|<d2>#2 $mi1}}",style=dotted]
115+
// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
116+
// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
117+
// CHECK-NEXT: Node[[N3]]:e -> Pred[[P3]]:d1:s [style=dotted]
118+
// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P4]]:d1:s [style=dotted]
119+
// CHECK-NEXT: Node[[N3]]:s1:n -> Pred[[P4]]:d2:s [style=dotted]
120+
// CHECK-NEXT: {{^}$}}
121+
122+
def nonstandardroot : GICombineRule<
123+
(defs root:$s),
124+
(match (MOV $s, $s2),
125+
(MOV $d1, $s),
126+
(MOV $d2, $s)),
127+
(apply [{ APPLY }])>;
128+
129+
// CHECK-LABEL: Parsed rule defs/match for 'nonstandardroot'
130+
131+
// CHECK-NEXT: matchdag {
132+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_0 // $s=getOperand(0), $s2=getOperand(1)
133+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_2 // $d1=getOperand(0), $s=getOperand(1)
134+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_4 // $d2=getOperand(0), $s=getOperand(1)
135+
// CHECK-NEXT: __anon3_2[src1] --[s]--> __anon3_0[dst]
136+
// CHECK-NEXT: __anon3_4[src1] --[s]--> __anon3_0[dst]
137+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_1
138+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_3
139+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_5
140+
// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred3_6
141+
// CHECK-NEXT: __anon3_0 ==> __anonpred3_1[mi]
142+
// CHECK-NEXT: __anon3_2 ==> __anonpred3_3[mi]
143+
// CHECK-NEXT: __anon3_4 ==> __anonpred3_5[mi]
144+
// CHECK-NEXT: __anon3_2[src1] ==> __anonpred3_6[mi0]
145+
// CHECK-NEXT: __anon3_4[src1] ==> __anonpred3_6[mi1]
146+
// CHECK-NEXT: {{^}$}}
147+
148+
// CHECK-NEXT: digraph "nonstandardroot" {
149+
// CHECK-NEXT: rankdir="BT"
150+
// CHECK-NEXT: Node[[N1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon3_0|MOV|Match starts here|$s=getOperand(0), $s2=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
151+
// CHECK-NEXT: Node[[N2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon3_2|MOV|$d1=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}"]
152+
// CHECK-NEXT: Node[[N3:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon3_4|MOV|$d2=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}"]
153+
// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
154+
// CHECK-NEXT: Node[[N3]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
155+
// CHECK-NEXT: Pred[[P1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred3_1|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
156+
// CHECK-NEXT: Pred[[P2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred3_3|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
157+
// CHECK-NEXT: Pred[[P3:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred3_5|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
158+
// CHECK-NEXT: Pred[[P4:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi0|<s2>#2 $mi1}|__anonpred3_6|$mi0 == $mi1|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi0|<d2>#2 $mi1}}",style=dotted]
159+
// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
160+
// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
161+
// CHECK-NEXT: Node[[N3]]:e -> Pred[[P3]]:d1:s [style=dotted]
162+
// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P4]]:d1:s [style=dotted]
163+
// CHECK-NEXT: Node[[N3]]:s1:n -> Pred[[P4]]:d2:s [style=dotted]
164+
// CHECK-NEXT: {{^}$}}
165+
166+
def multiref_use : GICombineRule<
167+
(defs root:$d1, root:$d2),
168+
(match (MOV $d1, $s),
169+
(MOV $d2, $s)),
170+
(apply [{ APPLY }])>;
171+
172+
// CHECK-LABEL: Parsed rule defs/match for 'multiref_use'
173+
174+
// CHECK-NEXT: matchdag {
175+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon4_0 // $d1=getOperand(0), $s=getOperand(1)
176+
// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon4_2 // $d2=getOperand(0), $s=getOperand(1)
177+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred4_1
178+
// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred4_3
179+
// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred4_4
180+
// CHECK-NEXT: __anon4_0 ==> __anonpred4_1[mi]
181+
// CHECK-NEXT: __anon4_2 ==> __anonpred4_3[mi]
182+
// CHECK-NEXT: __anon4_0[src1] ==> __anonpred4_4[mi0]
183+
// CHECK-NEXT: __anon4_2[src1] ==> __anonpred4_4[mi1]
184+
// CHECK-NEXT: {{^}$}}
185+
186+
// CHECK-NEXT: digraph "multiref_use" {
187+
// CHECK-NEXT: rankdir="BT"
188+
// CHECK-NEXT: Node[[N1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon4_0|MOV|Match starts here|$d1=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
189+
// CHECK-NEXT: Node[[N2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $dst|<s1>#1 $src1}|__anon4_2|MOV|Match starts here|$d2=getOperand(0), $s=getOperand(1)|{{0x[0-9a-f]+}}|{<d0>#0 $dst|<d1>#1 $src1}}",color=red]
190+
// CHECK-NEXT: Pred[[P1:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred4_1|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
191+
// CHECK-NEXT: Pred[[P2:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi}|__anonpred4_3|$mi.getOpcode() == MOV|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi}}",style=dotted]
192+
// CHECK-NEXT: Pred[[P3:0x[0-9a-f]+]] [shape=record,label="{{[{]{}}<s0>#0 $$|<s1>#1 $mi0|<s2>#2 $mi1}|__anonpred4_4|$mi0 == $mi1|{{0x[0-9a-f]+}}|{<d0>#0 $$|<d1>#1 $mi0|<d2>#2 $mi1}}",style=dotted]
193+
// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
194+
// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
195+
// CHECK-NEXT: Node[[N1]]:s1:n -> Pred[[P3]]:d1:s [style=dotted]
196+
// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P3]]:d2:s [style=dotted]
197+
// CHECK-NEXT: {{^}$}}
198+
199+
def MyCombiner: GICombinerHelper<"GenMyCombiner", [
200+
trivial,
201+
simple,
202+
multiroot,
203+
nonstandardroot,
204+
multiref_use
205+
]>;
206+
207+
// Verify we're sharing operand lists correctly
208+
// CHECK-LABEL: GIMatchDagOperandListContext {
209+
// CHECK-NEXT: OperandLists {
210+
// CHECK-NEXT: 0:dst<def>, 1:src1
211+
// CHECK-NEXT: 0:$<def>, 1:mi
212+
// CHECK-NEXT: 0:$<def>, 1:mi0, 2:mi1
213+
// CHECK-NEXT: }
214+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)