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