312 lines
11 KiB
TableGen
312 lines
11 KiB
TableGen
// RUN: not llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
|
|
// RUN: -combiners=MyCombiner %s 2>&1| \
|
|
// RUN: FileCheck %s -implicit-check-not=error:
|
|
|
|
include "llvm/Target/Target.td"
|
|
include "llvm/Target/GlobalISel/Combine.td"
|
|
|
|
def MyTargetISA : InstrInfo;
|
|
def MyTarget : Target { let InstructionSet = MyTargetISA; }
|
|
|
|
def dummy;
|
|
|
|
def MatchFooPerms: GICombinePatFrag<
|
|
(outs),
|
|
(ins gi_mo:$foo, gi_imm:$cst),
|
|
[
|
|
(pattern "return foo(${foo}, ${cst})"),
|
|
(pattern "return bar(${foo}, ${cst})"),
|
|
(pattern "return bux(${foo}, ${cst})"),
|
|
]>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: cannot emit rule 'too_many_perms'; 27 permutations would be emitted, but the max is 16
|
|
let MaxPermutations = 16 in
|
|
def too_many_perms : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $cst),
|
|
(MatchFooPerms $cst, (i32 0)):$a,
|
|
(MatchFooPerms $cst, (i32 0)):$b,
|
|
(MatchFooPerms $cst, (i32 0)):$c
|
|
),
|
|
(apply (COPY $dst, (i32 0)), "APPLY ${src}")>;
|
|
|
|
def DummyCXXPF: GICombinePatFrag<
|
|
(outs),
|
|
(ins gi_mo:$in),
|
|
[
|
|
(pattern "return foo()"),
|
|
]>;
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: operand 'foo' (for parameter 'in' of 'DummyCXXPF') cannot be unbound
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: note: one or more alternatives of 'DummyCXXPF' do not bind 'in' to an instruction operand; either use a bound operand or ensure 'DummyCXXPF' binds 'in' in all alternatives
|
|
def undef_livein : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $bar),
|
|
(DummyCXXPF $foo)
|
|
),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: GICombinePatFrag must have one root in its 'out' operands
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'OutMustBeRoot'
|
|
def OutMustBeRoot: GICombinePatFrag<
|
|
(outs $foo, $bar),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $foo, $bar), (G_FPEXT $bar, $y)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(OutMustBeRoot ?:$bar, ?:$foo)'
|
|
def out_must_be_root : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $bar),
|
|
(OutMustBeRoot $bar, $foo)
|
|
),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: output parameter 'bar' must be 'root' or 'gi_mo'
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'BadOutType'
|
|
def BadOutType: GICombinePatFrag<
|
|
(outs root:$foo, gi_imm:$bar),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $foo, $bar), (G_FPEXT $bar, $y)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(BadOutType ?:$bar, ?:$foo)'
|
|
def bad_out_type : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $bar),
|
|
(BadOutType $bar, $foo)
|
|
),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: pattern 'dbg' ('G_FPEXT') is unreachable from the pattern root!
|
|
def UnreachablePat: GICombinePatFrag<
|
|
(outs root:$foo, $bar),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $foo, $x), (G_FPEXT $bar, $y):$dbg),
|
|
]>;
|
|
def unreachable_pat : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $bar),
|
|
(UnreachablePat $bar, $foo)
|
|
),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: wip_match_opcode cannot be used in GICombinePatFrag
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'WipMatchOpcodePatFrag'
|
|
def WipMatchOpcodePatFrag: GICombinePatFrag<
|
|
(outs),
|
|
(ins),
|
|
[
|
|
(pattern (wip_match_opcode G_ZEXT)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(WipMatchOpcodePatFrag)'
|
|
def wip_match_opcode_patfrag : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (WipMatchOpcodePatFrag)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
def DummyPF: GICombinePatFrag<(outs),(ins),[]>;
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: nested GICombinePatFrag are not supported
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'NestingPatFrag'
|
|
def NestingPatFrag: GICombinePatFrag<
|
|
(outs),
|
|
(ins),
|
|
[
|
|
(pattern (DummyPF)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(NestingPatFrag)'
|
|
def nest_pat_frag : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (NestingPatFrag)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: input parameter 'k' cannot be redefined!
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'DupParamIn'
|
|
def DupParamIn: GICombinePatFrag<
|
|
(outs),
|
|
(ins gi_mo:$k, gi_mo:$k),
|
|
[
|
|
(pattern (G_ZEXT $k, $x)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(DupParamIn ?:$dst, ?:$bar)'
|
|
def dup_params_in : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (DupParamIn $dst, $bar)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: duplicate parameter 'k'
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'DupParamOut'
|
|
def DupParamOut: GICombinePatFrag<
|
|
(outs root:$k, root:$k),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $k, $x)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(DupParamOut ?:$dst, ?:$bar)'
|
|
def dup_params_out : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (DupParamOut $dst, $bar)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: input parameter 'k' cannot be redefined!
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'DupParamInOut'
|
|
def DupParamInOut: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins gi_mo:$k),
|
|
[
|
|
(pattern (G_ZEXT $k, $x)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(DupParamInOut ?:$dst, ?:$bar)'
|
|
def dup_params_inout : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (DupParamInOut $dst, $bar)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: output parameter 'k' must be defined by all alternative patterns in 'DefByAllAlts'
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'DefByAllAlts'
|
|
def DefByAllAlts: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $k, $x)),
|
|
(pattern (G_FPEXT $z, $k))
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(DefByAllAlts ?:$dst)'
|
|
def def_by_all_alts : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (DefByAllAlts $dst)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: Operand 'x' is defined multiple times in patterns of alternative #1
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'MultiDefInPat'
|
|
def MultiDefInPat: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins),
|
|
[
|
|
(pattern (G_ZEXT $k, $a)),
|
|
(pattern (G_ZEXT $k, $x), (G_ZEXT $x, $foo), (G_FPEXT $x, $foo)),
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(MultiDefInPat ?:$dst)'
|
|
def multi_def_in_pat : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (MultiDefInPat $dst)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
def ExpectedImm: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins gi_imm:$i),
|
|
[
|
|
(pattern (G_ZEXT $k, $i)),
|
|
]>;
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: expected operand 1 of 'ExpectedImm' to be an immediate; got MachineOperand $z
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(ExpectedImm ?:$dst, ?:$z)'
|
|
def expected_imm : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (ExpectedImm $dst, $z)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: operand 1 of 'ExpectedImm' cannot be a named immediate
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(ExpectedImm ?:$dst, (i32 0):$z)'
|
|
def expected_imm_namedimm : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (ExpectedImm $dst, (i32 0):$z)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
def ExpectedMO: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins gi_mo:$i),
|
|
[
|
|
(pattern (G_ZEXT $k, $i)),
|
|
]>;
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: expected operand 1 of 'ExpectedMO' to be a MachineOperand; got imm 0
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(ExpectedMO ?:$dst, (i32 0))'
|
|
def expected_mo : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (ExpectedMO $dst, (i32 0))),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: expected operand 1 of 'ExpectedMO' to be a MachineOperand; got imm 0:$z
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(ExpectedMO ?:$dst, (i32 0):$z)'
|
|
def expected_mo_namedimm : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (ExpectedMO $dst, (i32 0):$z)),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'dum': using GICombinePatFrag is not supported in apply patterns
|
|
def patfrag_in_apply : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (COPY $dst, (i32 0))),
|
|
(apply (DummyPF):$dum)>;
|
|
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: cannot use 'DummyPF as match root
|
|
def patfrag_cannot_be_root : GICombineRule<
|
|
(defs root:$root),
|
|
(match (DummyPF):$root),
|
|
(apply (COPY $dst, (i32 0)):$root)>;
|
|
|
|
def TypedParams: GICombinePatFrag<
|
|
(outs root:$k),
|
|
(ins gi_mo:$i),
|
|
[
|
|
(pattern (G_ZEXT $k, i32:$i)),
|
|
]>;
|
|
// CHECK: :[[@LINE+3]]:{{[0-9]+}}: warning: impossible type constraints: operand 1 of 'broken' has type 'i64', but 'TypedParams' constrains it to 'i32'
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: note: operand 1 of 'broken' is 'k'
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: note: argument 1 of 'TypedParams' is 'i'
|
|
def inconsistent_arg_type : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (TypedParams $dst, i64:$k):$broken),
|
|
(apply (COPY $dst, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: all instructions that define root 'foo' in 'RootDefHasMultiDefs' can only have a single output operand
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'RootDefHasMultiDefs'
|
|
def RootDefHasMultiDefs: GICombinePatFrag<
|
|
(outs root:$foo),
|
|
(ins gi_imm:$cst),
|
|
[
|
|
(pattern (G_UNMERGE_VALUES $foo, $z, $y))
|
|
]>;
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(RootDefHasMultiDefs ?:$root, (i32 10))'
|
|
def root_def_has_multi_defs : GICombineRule<
|
|
(defs root:$root),
|
|
(match (RootDefHasMultiDefs $root, (i32 10))),
|
|
(apply (COPY $root, (i32 0)))>;
|
|
|
|
// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: matching/writing MIFlags is only allowed on CodeGenInstruction patterns
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(DummyCXXPF ?:$x, (MIFlags FmArcp))'
|
|
def miflags_in_pf : GICombineRule<
|
|
(defs root:$x),
|
|
(match (COPY $x, $y), (DummyCXXPF $x, (MIFlags FmArcp))),
|
|
(apply (COPY $x, $y))>;
|
|
|
|
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: '$pf' does not refer to a CodeGenInstruction in MIFlags of '__badtype_for_flagref_in_apply_apply_0'
|
|
def badtype_for_flagref_in_apply : GICombineRule<
|
|
(defs root:$dst),
|
|
(match (G_ZEXT $dst, $src), (DummyCXXPF $src):$pf),
|
|
(apply (G_MUL $dst, $src, $src, (MIFlags $pf)))>;
|
|
|
|
// CHECK: error: Failed to parse one or more rules
|
|
|
|
def MyCombiner: GICombiner<"GenMyCombiner", [
|
|
too_many_perms,
|
|
undef_livein,
|
|
out_must_be_root,
|
|
bad_out_type,
|
|
unreachable_pat,
|
|
wip_match_opcode_patfrag,
|
|
nest_pat_frag,
|
|
dup_params_in,
|
|
dup_params_out,
|
|
dup_params_inout,
|
|
def_by_all_alts,
|
|
multi_def_in_pat,
|
|
expected_imm,
|
|
expected_imm_namedimm,
|
|
expected_mo,
|
|
expected_mo_namedimm,
|
|
patfrag_in_apply,
|
|
patfrag_cannot_be_root,
|
|
inconsistent_arg_type,
|
|
root_def_has_multi_defs,
|
|
miflags_in_pf,
|
|
badtype_for_flagref_in_apply
|
|
]>;
|