1//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// Declare GlobalISel combine rules and provide mechanisms to opt-out. 10// 11//===----------------------------------------------------------------------===// 12 13// Common base class for GICombineRule and GICombineGroup. 14class GICombine { 15 // See GICombineGroup. We only declare it here to make the tablegen pass 16 // simpler. 17 list<GICombine> Rules = ?; 18} 19 20// A group of combine rules that can be added to a GICombiner or another group. 21class GICombineGroup<list<GICombine> rules> : GICombine { 22 // The rules contained in this group. The rules in a group are flattened into 23 // a single list and sorted into whatever order is most efficient. However, 24 // they will never be re-ordered such that behaviour differs from the 25 // specified order. It is therefore possible to use the order of rules in this 26 // list to describe priorities. 27 let Rules = rules; 28} 29 30// Declares a combiner helper class 31class GICombinerHelper<string classname, list<GICombine> rules> 32 : GICombineGroup<rules> { 33 // The class name to use in the generated output. 34 string Classname = classname; 35 // The name of a run-time compiler option that will be generated to disable 36 // specific rules within this combiner. 37 string DisableRuleOption = ?; 38} 39class GICombineRule<dag defs, dag match, dag apply> : GICombine { 40 /// Defines the external interface of the match rule. This includes: 41 /// * The names of the root nodes (requires at least one) 42 /// See GIDefKind for details. 43 dag Defs = defs; 44 45 /// Defines the things which must be true for the pattern to match 46 /// See GIMatchKind for details. 47 dag Match = match; 48 49 /// Defines the things which happen after the decision is made to apply a 50 /// combine rule. 51 /// See GIApplyKind for details. 52 dag Apply = apply; 53} 54 55/// The operator at the root of a GICombineRule.Defs dag. 56def defs; 57 58/// All arguments of the defs operator must be subclasses of GIDefKind or 59/// sub-dags whose operator is GIDefKindWithArgs. 60class GIDefKind; 61class GIDefKindWithArgs; 62/// Declare a root node. There must be at least one of these in every combine 63/// rule. 64/// TODO: The plan is to elide `root` definitions and determine it from the DAG 65/// itself with an overide for situations where the usual determination 66/// is incorrect. 67def root : GIDefKind; 68 69/// Declares data that is passed from the match stage to the apply stage. 70class GIDefMatchData<string type> : GIDefKind { 71 /// A C++ type name indicating the storage type. 72 string Type = type; 73} 74 75def extending_load_matchdata : GIDefMatchData<"PreferredTuple">; 76def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">; 77 78/// The operator at the root of a GICombineRule.Match dag. 79def match; 80/// All arguments of the match operator must be either: 81/// * A subclass of GIMatchKind 82/// * A subclass of GIMatchKindWithArgs 83/// * A subclass of Instruction 84/// * A MIR code block (deprecated) 85/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail 86/// in their definitions below. 87/// For the Instruction case, these are collected into a DAG where operand names 88/// that occur multiple times introduce edges. 89class GIMatchKind; 90class GIMatchKindWithArgs; 91 92/// In lieu of having proper macro support. Trivial one-off opcode checks can be 93/// performed with this. 94def wip_match_opcode : GIMatchKindWithArgs; 95 96/// The operator at the root of a GICombineRule.Apply dag. 97def apply; 98/// All arguments of the apply operator must be subclasses of GIApplyKind, or 99/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block 100/// (deprecated). 101class GIApplyKind; 102class GIApplyKindWithArgs; 103 104def copy_prop : GICombineRule< 105 (defs root:$d), 106 (match (COPY $d, $s):$mi, 107 [{ return Helper.matchCombineCopy(*${mi}); }]), 108 (apply [{ Helper.applyCombineCopy(*${mi}); }])>; 109def trivial_combines : GICombineGroup<[copy_prop]>; 110 111def extending_loads : GICombineRule< 112 (defs root:$root, extending_load_matchdata:$matchinfo), 113 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, 114 [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), 115 (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; 116def combines_for_extload: GICombineGroup<[extending_loads]>; 117 118def combine_indexed_load_store : GICombineRule< 119 (defs root:$root, indexed_load_store_matchdata:$matchinfo), 120 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, 121 [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), 122 (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; 123 124// FIXME: Is there a reason this wasn't in tryCombine? I've left it out of 125// all_combines because it wasn't there. 126def elide_br_by_inverting_cond : GICombineRule< 127 (defs root:$root), 128 (match (wip_match_opcode G_BR):$root, 129 [{ return Helper.matchElideBrByInvertingCond(*${root}); }]), 130 (apply [{ Helper.applyElideBrByInvertingCond(*${root}); }])>; 131 132def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; 133def ptr_add_immed_chain : GICombineRule< 134 (defs root:$d, ptr_add_immed_matchdata:$matchinfo), 135 (match (wip_match_opcode G_PTR_ADD):$d, 136 [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), 137 (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; 138 139def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain, 140 combines_for_extload, combine_indexed_load_store]>; 141