summaryrefslogtreecommitdiffstats
path: root/llvm/test/TableGen
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2019-12-17 14:29:14 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2019-12-17 15:28:03 +0000
commit390c8baa5440dda8907688d9ef860f6982bd925f (patch)
treec2d470b68485ff8670787a354397c76fb9826183 /llvm/test/TableGen
parent268f37df6e45c4b0603bd4d964483a0d84da44c1 (diff)
downloadbcm5719-llvm-390c8baa5440dda8907688d9ef860f6982bd925f.tar.gz
bcm5719-llvm-390c8baa5440dda8907688d9ef860f6982bd925f.zip
[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
Diffstat (limited to 'llvm/test/TableGen')
-rw-r--r--llvm/test/TableGen/GICombinerEmitter/match-invalid.td10
-rw-r--r--llvm/test/TableGen/GICombinerEmitter/parse-match-pattern.td214
2 files changed, 224 insertions, 0 deletions
diff --git a/llvm/test/TableGen/GICombinerEmitter/match-invalid.td b/llvm/test/TableGen/GICombinerEmitter/match-invalid.td
index 2d67f1ea549..8d7ed8006c9 100644
--- a/llvm/test/TableGen/GICombinerEmitter/match-invalid.td
+++ b/llvm/test/TableGen/GICombinerEmitter/match-invalid.td
@@ -53,6 +53,15 @@ def unknown_kind2 : GICombineRule<
// CHECK-NEXT: def unknown_kind2 : GICombineRule<
// CHECK: :[[@LINE-6]]:{{[0-9]+}}: error: Failed to parse rule
+def multidef : GICombineRule<
+ (defs root:$a),
+ (match (MOV $a, $b),
+ (MOV $a, $b)),
+ (dummy)>;
+// CHECK: :[[@LINE-5]]:{{[0-9]+}}: error: Two different MachineInstrs cannot def the same vreg
+// CHECK-NEXT: def multidef : GICombineRule<
+// CHECK: :[[@LINE-7]]:{{[0-9]+}}: error: Failed to parse rule
+
def multidef_but_not_an_error: GICombineRule<
(defs root:$a),
(match (MOV $a, $b),
@@ -66,6 +75,7 @@ def MyCombiner: GICombinerHelper<"GenMyCombiner", [
null_matcher,
unknown_kind1,
unknown_kind2,
+ multidef
// Rules omitted from a matcher can be as broken as you like. They will not be read.
// multidef_but_not_an_error
]>;
diff --git a/llvm/test/TableGen/GICombinerEmitter/parse-match-pattern.td b/llvm/test/TableGen/GICombinerEmitter/parse-match-pattern.td
new file mode 100644
index 00000000000..b53908d180e
--- /dev/null
+++ b/llvm/test/TableGen/GICombinerEmitter/parse-match-pattern.td
@@ -0,0 +1,214 @@
+// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
+// RUN: -combiners=MyCombiner -gicombiner-stop-after-parse %s \
+// RUN: -o /dev/null -debug 2>&1 | FileCheck %s
+
+include "llvm/Target/Target.td"
+include "llvm/Target/GlobalISel/Combine.td"
+
+def MyTargetISA : InstrInfo;
+def MyTarget : Target { let InstructionSet = MyTargetISA; }
+
+def dummy;
+
+def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
+def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
+class I<dag OOps, dag IOps, list<dag> Pat>
+ : Instruction {
+ let Namespace = "MyTarget";
+ let OutOperandList = OOps;
+ let InOperandList = IOps;
+ let Pattern = Pat;
+}
+def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1), []>;
+def MOV2 : I<(outs GPR32:$dst), (ins GPR32:$src1), []>;
+
+def trivial : GICombineRule<
+ (defs root:$d),
+ (match (MOV $d, $s)),
+ (apply [{ APPLY }])>;
+
+// CHECK-LABEL: Parsed rule defs/match for 'trivial'
+
+// The matchdag block is a fairly direct dump of the information that was read.
+// It's oriented towards the data structures within tablegen.
+// CHECK-NEXT: matchdag {
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon0_0 // $d=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred0_1
+// CHECK-NEXT: __anon0_0 ==> __anonpred0_1[mi]
+// CHECK-NEXT: {{^}$}}
+
+// The digraph block is a human-oriented dump of the information that was read.
+// Run it through graphviz to produce a nice DAG showing the matcher behaviour.
+// CHECK-NEXT: digraph "trivial" {
+// CHECK-NEXT: rankdir="BT"
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
+// CHECK-NEXT: {{^}$}}
+
+def simple : GICombineRule<
+ (defs root:$d),
+ (match (MOV $t, $s),
+ (MOV $d, $t)),
+ (apply [{ APPLY }])>;
+
+// CHECK-LABEL: Parsed rule defs/match for 'simple'
+
+// CHECK-NEXT: matchdag {
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon1_0 // $t=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon1_2 // $d=getOperand(0), $t=getOperand(1)
+// CHECK-NEXT: __anon1_2[src1] --[t]--> __anon1_0[dst]
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred1_1
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred1_3
+// CHECK-NEXT: __anon1_0 ==> __anonpred1_1[mi]
+// CHECK-NEXT: __anon1_2 ==> __anonpred1_3[mi]
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-NEXT: digraph "simple" {
+// CHECK-NEXT: rankdir="BT"
+// 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}}"]
+// 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]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$t"]
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
+// CHECK-NEXT: {{^}$}}
+
+def multiroot : GICombineRule<
+ (defs root:$d1, root:$d2),
+ (match (MOV $s, $s2),
+ (MOV $d1, $s),
+ (MOV $d2, $s)),
+ (apply [{ APPLY }])>;
+
+// CHECK-LABEL: Parsed rule defs/match for 'multiroot'
+
+// CHECK-NEXT: matchdag {
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_0 // $s=getOperand(0), $s2=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_2 // $d1=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon2_4 // $d2=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: __anon2_2[src1] --[s]--> __anon2_0[dst]
+// CHECK-NEXT: __anon2_4[src1] --[s]--> __anon2_0[dst]
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_1
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_3
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred2_5
+// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred2_6
+// CHECK-NEXT: __anon2_0 ==> __anonpred2_1[mi]
+// CHECK-NEXT: __anon2_2 ==> __anonpred2_3[mi]
+// CHECK-NEXT: __anon2_4 ==> __anonpred2_5[mi]
+// CHECK-NEXT: __anon2_2[src1] ==> __anonpred2_6[mi0]
+// CHECK-NEXT: __anon2_4[src1] ==> __anonpred2_6[mi1]
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-NEXT: digraph "multiroot" {
+// CHECK-NEXT: rankdir="BT"
+// 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}}"]
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
+// CHECK-NEXT: Node[[N3]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
+// 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]
+// 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]
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N3]]:e -> Pred[[P3]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P4]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N3]]:s1:n -> Pred[[P4]]:d2:s [style=dotted]
+// CHECK-NEXT: {{^}$}}
+
+def nonstandardroot : GICombineRule<
+ (defs root:$s),
+ (match (MOV $s, $s2),
+ (MOV $d1, $s),
+ (MOV $d2, $s)),
+ (apply [{ APPLY }])>;
+
+// CHECK-LABEL: Parsed rule defs/match for 'nonstandardroot'
+
+// CHECK-NEXT: matchdag {
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_0 // $s=getOperand(0), $s2=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_2 // $d1=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon3_4 // $d2=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: __anon3_2[src1] --[s]--> __anon3_0[dst]
+// CHECK-NEXT: __anon3_4[src1] --[s]--> __anon3_0[dst]
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_1
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_3
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred3_5
+// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred3_6
+// CHECK-NEXT: __anon3_0 ==> __anonpred3_1[mi]
+// CHECK-NEXT: __anon3_2 ==> __anonpred3_3[mi]
+// CHECK-NEXT: __anon3_4 ==> __anonpred3_5[mi]
+// CHECK-NEXT: __anon3_2[src1] ==> __anonpred3_6[mi0]
+// CHECK-NEXT: __anon3_4[src1] ==> __anonpred3_6[mi1]
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-NEXT: digraph "nonstandardroot" {
+// CHECK-NEXT: rankdir="BT"
+// 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]
+// 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}}"]
+// 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}}"]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
+// CHECK-NEXT: Node[[N3]]:s1:n -> Node[[N1]]:d0:s [label="$s"]
+// 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]
+// 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]
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N3]]:e -> Pred[[P3]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P4]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N3]]:s1:n -> Pred[[P4]]:d2:s [style=dotted]
+// CHECK-NEXT: {{^}$}}
+
+def multiref_use : GICombineRule<
+ (defs root:$d1, root:$d2),
+ (match (MOV $d1, $s),
+ (MOV $d2, $s)),
+ (apply [{ APPLY }])>;
+
+// CHECK-LABEL: Parsed rule defs/match for 'multiref_use'
+
+// CHECK-NEXT: matchdag {
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon4_0 // $d1=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: (MOV 0:dst<def>, 1:src1):$__anon4_2 // $d2=getOperand(0), $s=getOperand(1)
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred4_1
+// CHECK-NEXT: <<$mi.getOpcode() == MOV>>:$__anonpred4_3
+// CHECK-NEXT: <<$mi0 == $mi1>>:$__anonpred4_4
+// CHECK-NEXT: __anon4_0 ==> __anonpred4_1[mi]
+// CHECK-NEXT: __anon4_2 ==> __anonpred4_3[mi]
+// CHECK-NEXT: __anon4_0[src1] ==> __anonpred4_4[mi0]
+// CHECK-NEXT: __anon4_2[src1] ==> __anonpred4_4[mi1]
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-NEXT: digraph "multiref_use" {
+// CHECK-NEXT: rankdir="BT"
+// 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]
+// 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]
+// 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]
+// 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]
+// 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]
+// CHECK-NEXT: Node[[N1]]:e -> Pred[[P1]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:e -> Pred[[P2]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N1]]:s1:n -> Pred[[P3]]:d1:s [style=dotted]
+// CHECK-NEXT: Node[[N2]]:s1:n -> Pred[[P3]]:d2:s [style=dotted]
+// CHECK-NEXT: {{^}$}}
+
+def MyCombiner: GICombinerHelper<"GenMyCombiner", [
+ trivial,
+ simple,
+ multiroot,
+ nonstandardroot,
+ multiref_use
+]>;
+
+// Verify we're sharing operand lists correctly
+// CHECK-LABEL: GIMatchDagOperandListContext {
+// CHECK-NEXT: OperandLists {
+// CHECK-NEXT: 0:dst<def>, 1:src1
+// CHECK-NEXT: 0:$<def>, 1:mi
+// CHECK-NEXT: 0:$<def>, 1:mi0, 2:mi1
+// CHECK-NEXT: }
+// CHECK-NEXT: }
OpenPOWER on IntegriCloud