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 30class GICombinerHelperArg<string type, string name> { 31 string Type = type; 32 string Name = name; 33} 34 35// Declares a combiner helper class 36class GICombinerHelper<string classname, list<GICombine> rules> 37 : GICombineGroup<rules> { 38 // The class name to use in the generated output. 39 string Classname = classname; 40 // The name of a run-time compiler option that will be generated to disable 41 // specific rules within this combiner. 42 string DisableRuleOption = ?; 43 // The state class to inherit from (if any). The generated helper will inherit 44 // from this class and will forward arguments to its constructors. 45 string StateClass = ""; 46 // Any additional arguments that should be appended to the tryCombine*(). 47 list<GICombinerHelperArg> AdditionalArguments = 48 [GICombinerHelperArg<"CombinerHelper &", "Helper">]; 49} 50class GICombineRule<dag defs, dag match, dag apply> : GICombine { 51 /// Defines the external interface of the match rule. This includes: 52 /// * The names of the root nodes (requires at least one) 53 /// See GIDefKind for details. 54 dag Defs = defs; 55 56 /// Defines the things which must be true for the pattern to match 57 /// See GIMatchKind for details. 58 dag Match = match; 59 60 /// Defines the things which happen after the decision is made to apply a 61 /// combine rule. 62 /// See GIApplyKind for details. 63 dag Apply = apply; 64} 65 66/// The operator at the root of a GICombineRule.Defs dag. 67def defs; 68 69/// All arguments of the defs operator must be subclasses of GIDefKind or 70/// sub-dags whose operator is GIDefKindWithArgs. 71class GIDefKind; 72class GIDefKindWithArgs; 73/// Declare a root node. There must be at least one of these in every combine 74/// rule. 75/// TODO: The plan is to elide `root` definitions and determine it from the DAG 76/// itself with an overide for situations where the usual determination 77/// is incorrect. 78def root : GIDefKind; 79 80/// Declares data that is passed from the match stage to the apply stage. 81class GIDefMatchData<string type> : GIDefKind { 82 /// A C++ type name indicating the storage type. 83 string Type = type; 84} 85 86def extending_load_matchdata : GIDefMatchData<"PreferredTuple">; 87def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">; 88 89/// The operator at the root of a GICombineRule.Match dag. 90def match; 91/// All arguments of the match operator must be either: 92/// * A subclass of GIMatchKind 93/// * A subclass of GIMatchKindWithArgs 94/// * A subclass of Instruction 95/// * A MIR code block (deprecated) 96/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail 97/// in their definitions below. 98/// For the Instruction case, these are collected into a DAG where operand names 99/// that occur multiple times introduce edges. 100class GIMatchKind; 101class GIMatchKindWithArgs; 102 103/// In lieu of having proper macro support. Trivial one-off opcode checks can be 104/// performed with this. 105def wip_match_opcode : GIMatchKindWithArgs; 106 107/// The operator at the root of a GICombineRule.Apply dag. 108def apply; 109/// All arguments of the apply operator must be subclasses of GIApplyKind, or 110/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block 111/// (deprecated). 112class GIApplyKind; 113class GIApplyKindWithArgs; 114 115def copy_prop : GICombineRule< 116 (defs root:$d), 117 (match (COPY $d, $s):$mi, 118 [{ return Helper.matchCombineCopy(*${mi}); }]), 119 (apply [{ Helper.applyCombineCopy(*${mi}); }])>; 120 121def extending_loads : GICombineRule< 122 (defs root:$root, extending_load_matchdata:$matchinfo), 123 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, 124 [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), 125 (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; 126def combines_for_extload: GICombineGroup<[extending_loads]>; 127 128def sext_already_extended : GICombineRule< 129 (defs root:$d), 130 (match (wip_match_opcode G_SEXT_INREG):$d, 131 [{ return Helper.matchSextAlreadyExtended(*${d}); }]), 132 (apply [{ Helper.applySextAlreadyExtended(*${d}); }])>; 133 134def combine_indexed_load_store : GICombineRule< 135 (defs root:$root, indexed_load_store_matchdata:$matchinfo), 136 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, 137 [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), 138 (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; 139 140// FIXME: Is there a reason this wasn't in tryCombine? I've left it out of 141// all_combines because it wasn't there. 142def elide_br_by_inverting_cond : GICombineRule< 143 (defs root:$root), 144 (match (wip_match_opcode G_BR):$root, 145 [{ return Helper.matchElideBrByInvertingCond(*${root}); }]), 146 (apply [{ Helper.applyElideBrByInvertingCond(*${root}); }])>; 147 148def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; 149def ptr_add_immed_chain : GICombineRule< 150 (defs root:$d, ptr_add_immed_matchdata:$matchinfo), 151 (match (wip_match_opcode G_PTR_ADD):$d, 152 [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), 153 (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; 154 155def mul_to_shl_matchdata : GIDefMatchData<"unsigned">; 156def mul_to_shl : GICombineRule< 157 (defs root:$d, mul_to_shl_matchdata:$matchinfo), 158 (match (G_MUL $d, $op1, $op2):$mi, 159 [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]), 160 (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>; 161 162// [us]itofp(undef) = 0, because the result value is bounded. 163def undef_to_fp_zero : GICombineRule< 164 (defs root:$root), 165 (match (wip_match_opcode G_UITOFP, G_SITOFP):$root, 166 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 167 (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>; 168 169def undef_to_int_zero: GICombineRule< 170 (defs root:$root), 171 (match (wip_match_opcode G_AND, G_MUL):$root, 172 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 173 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 174 175def undef_to_negative_one: GICombineRule< 176 (defs root:$root), 177 (match (wip_match_opcode G_OR):$root, 178 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 179 (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>; 180 181// Instructions where if any source operand is undef, the instruction can be 182// replaced with undef. 183def propagate_undef_any_op: GICombineRule< 184 (defs root:$root), 185 (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR):$root, 186 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 187 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 188 189// Instructions where if all source operands are undef, the instruction can be 190// replaced with undef. 191def propagate_undef_all_ops: GICombineRule< 192 (defs root:$root), 193 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 194 [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]), 195 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 196 197// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF. 198def propagate_undef_shuffle_mask: GICombineRule< 199 (defs root:$root), 200 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 201 [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), 202 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 203 204// Fold (cond ? x : x) -> x 205def select_same_val: GICombineRule< 206 (defs root:$root), 207 (match (wip_match_opcode G_SELECT):$root, 208 [{ return Helper.matchSelectSameVal(*${root}); }]), 209 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 210>; 211 212// Fold x op 0 -> x 213def right_identity_zero: GICombineRule< 214 (defs root:$root), 215 (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR):$root, 216 [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]), 217 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 218>; 219 220// Fold (x op x) - > x 221def binop_same_val: GICombineRule< 222 (defs root:$root), 223 (match (wip_match_opcode G_AND, G_OR):$root, 224 [{ return Helper.matchBinOpSameVal(*${root}); }]), 225 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 226>; 227 228// Fold (0 op x) - > 0 229def binop_left_to_zero: GICombineRule< 230 (defs root:$root), 231 (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, 232 [{ return Helper.matchOperandIsZero(*${root}, 1); }]), 233 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 234>; 235 236// Fold (x op 0) - > 0 237def binop_right_to_zero: GICombineRule< 238 (defs root:$root), 239 (match (wip_match_opcode G_MUL):$root, 240 [{ return Helper.matchOperandIsZero(*${root}, 2); }]), 241 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 242>; 243 244// Erase stores of undef values. 245def erase_undef_store : GICombineRule< 246 (defs root:$root), 247 (match (wip_match_opcode G_STORE):$root, 248 [{ return Helper.matchUndefStore(*${root}); }]), 249 (apply [{ return Helper.eraseInst(*${root}); }]) 250>; 251 252def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">; 253def simplify_add_to_sub: GICombineRule < 254 (defs root:$root, simplify_add_to_sub_matchinfo:$info), 255 (match (wip_match_opcode G_ADD):$root, 256 [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]), 257 (apply [{ return Helper.applySimplifyAddToSub(*${root}, ${info});}]) 258>; 259 260// FIXME: These should use the custom predicate feature once it lands. 261def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, 262 undef_to_negative_one, 263 propagate_undef_any_op, 264 propagate_undef_all_ops, 265 propagate_undef_shuffle_mask, 266 erase_undef_store]>; 267 268def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, 269 binop_same_val, binop_left_to_zero, 270 binop_right_to_zero]>; 271 272def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>; 273def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain, 274 combines_for_extload, combine_indexed_load_store, undef_combines, 275 identity_combines, simplify_add_to_sub]>; 276