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