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">; 88def instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">; 89 90/// The operator at the root of a GICombineRule.Match dag. 91def match; 92/// All arguments of the match operator must be either: 93/// * A subclass of GIMatchKind 94/// * A subclass of GIMatchKindWithArgs 95/// * A subclass of Instruction 96/// * A MIR code block (deprecated) 97/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail 98/// in their definitions below. 99/// For the Instruction case, these are collected into a DAG where operand names 100/// that occur multiple times introduce edges. 101class GIMatchKind; 102class GIMatchKindWithArgs; 103 104/// In lieu of having proper macro support. Trivial one-off opcode checks can be 105/// performed with this. 106def wip_match_opcode : GIMatchKindWithArgs; 107 108/// The operator at the root of a GICombineRule.Apply dag. 109def apply; 110/// All arguments of the apply operator must be subclasses of GIApplyKind, or 111/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block 112/// (deprecated). 113class GIApplyKind; 114class GIApplyKindWithArgs; 115 116def copy_prop : GICombineRule< 117 (defs root:$d), 118 (match (COPY $d, $s):$mi, 119 [{ return Helper.matchCombineCopy(*${mi}); }]), 120 (apply [{ Helper.applyCombineCopy(*${mi}); }])>; 121 122def extending_loads : GICombineRule< 123 (defs root:$root, extending_load_matchdata:$matchinfo), 124 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, 125 [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), 126 (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; 127def combines_for_extload: GICombineGroup<[extending_loads]>; 128 129def sext_trunc_sextload : GICombineRule< 130 (defs root:$d), 131 (match (wip_match_opcode G_SEXT_INREG):$d, 132 [{ return Helper.matchSextTruncSextLoad(*${d}); }]), 133 (apply [{ Helper.applySextTruncSextLoad(*${d}); }])>; 134 135def sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple<Register, unsigned>">; 136def sext_inreg_of_load : GICombineRule< 137 (defs root:$root, sext_inreg_of_load_matchdata:$matchinfo), 138 (match (wip_match_opcode G_SEXT_INREG):$root, 139 [{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]), 140 (apply [{ return Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>; 141 142def combine_indexed_load_store : GICombineRule< 143 (defs root:$root, indexed_load_store_matchdata:$matchinfo), 144 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, 145 [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), 146 (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; 147 148def opt_brcond_by_inverting_cond : GICombineRule< 149 (defs root:$root), 150 (match (wip_match_opcode G_BR):$root, 151 [{ return Helper.matchOptBrCondByInvertingCond(*${root}); }]), 152 (apply [{ Helper.applyOptBrCondByInvertingCond(*${root}); }])>; 153 154def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; 155def ptr_add_immed_chain : GICombineRule< 156 (defs root:$d, ptr_add_immed_matchdata:$matchinfo), 157 (match (wip_match_opcode G_PTR_ADD):$d, 158 [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), 159 (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; 160 161// Fold shift (shift base x), y -> shift base, (x+y), if shifts are same 162def shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">; 163def shift_immed_chain : GICombineRule< 164 (defs root:$d, shift_immed_matchdata:$matchinfo), 165 (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d, 166 [{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]), 167 (apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>; 168 169// Transform shift (logic (shift X, C0), Y), C1 170// -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same 171def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">; 172def shift_of_shifted_logic_chain : GICombineRule< 173 (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo), 174 (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d, 175 [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]), 176 (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>; 177 178def mul_to_shl_matchdata : GIDefMatchData<"unsigned">; 179def mul_to_shl : GICombineRule< 180 (defs root:$d, mul_to_shl_matchdata:$matchinfo), 181 (match (G_MUL $d, $op1, $op2):$mi, 182 [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]), 183 (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>; 184 185// shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int 186def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">; 187def reduce_shl_of_extend : GICombineRule< 188 (defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo), 189 (match (G_SHL $dst, $src0, $src1):$mi, 190 [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]), 191 (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>; 192 193// [us]itofp(undef) = 0, because the result value is bounded. 194def undef_to_fp_zero : GICombineRule< 195 (defs root:$root), 196 (match (wip_match_opcode G_UITOFP, G_SITOFP):$root, 197 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 198 (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>; 199 200def undef_to_int_zero: GICombineRule< 201 (defs root:$root), 202 (match (wip_match_opcode G_AND, G_MUL):$root, 203 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 204 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 205 206def undef_to_negative_one: GICombineRule< 207 (defs root:$root), 208 (match (wip_match_opcode G_OR):$root, 209 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 210 (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>; 211 212def binop_left_undef_to_zero: GICombineRule< 213 (defs root:$root), 214 (match (wip_match_opcode G_SHL):$root, 215 [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), 216 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 217 218// Instructions where if any source operand is undef, the instruction can be 219// replaced with undef. 220def propagate_undef_any_op: GICombineRule< 221 (defs root:$root), 222 (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC):$root, 223 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 224 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 225 226// Instructions where if all source operands are undef, the instruction can be 227// replaced with undef. 228def propagate_undef_all_ops: GICombineRule< 229 (defs root:$root), 230 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 231 [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]), 232 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 233 234// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF. 235def propagate_undef_shuffle_mask: GICombineRule< 236 (defs root:$root), 237 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 238 [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), 239 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 240 241// Fold (cond ? x : x) -> x 242def select_same_val: GICombineRule< 243 (defs root:$root), 244 (match (wip_match_opcode G_SELECT):$root, 245 [{ return Helper.matchSelectSameVal(*${root}); }]), 246 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 247>; 248 249// Fold (undef ? x : y) -> y 250def select_undef_cmp: GICombineRule< 251 (defs root:$root), 252 (match (wip_match_opcode G_SELECT):$root, 253 [{ return Helper.matchUndefSelectCmp(*${root}); }]), 254 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 255>; 256 257// Fold (true ? x : y) -> x 258// Fold (false ? x : y) -> y 259def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">; 260def select_constant_cmp: GICombineRule< 261 (defs root:$root, select_constant_cmp_matchdata:$matchinfo), 262 (match (wip_match_opcode G_SELECT):$root, 263 [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]), 264 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }]) 265>; 266 267// Fold x op 0 -> x 268def right_identity_zero: GICombineRule< 269 (defs root:$root), 270 (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR):$root, 271 [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]), 272 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 273>; 274 275// Fold x op 1 -> x 276def right_identity_one: GICombineRule< 277 (defs root:$root), 278 (match (wip_match_opcode G_MUL):$root, 279 [{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]), 280 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 281>; 282 283// Fold (x op x) - > x 284def binop_same_val: GICombineRule< 285 (defs root:$root), 286 (match (wip_match_opcode G_AND, G_OR):$root, 287 [{ return Helper.matchBinOpSameVal(*${root}); }]), 288 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 289>; 290 291// Fold (0 op x) - > 0 292def binop_left_to_zero: GICombineRule< 293 (defs root:$root), 294 (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, 295 [{ return Helper.matchOperandIsZero(*${root}, 1); }]), 296 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 297>; 298 299def urem_pow2_to_mask : GICombineRule< 300 (defs root:$root), 301 (match (wip_match_opcode G_UREM):$root, 302 [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]), 303 (apply [{ return Helper.applySimplifyURemByPow2(*${root}); }]) 304>; 305 306// Fold (x op 0) - > 0 307def binop_right_to_zero: GICombineRule< 308 (defs root:$root), 309 (match (wip_match_opcode G_MUL):$root, 310 [{ return Helper.matchOperandIsZero(*${root}, 2); }]), 311 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 312>; 313 314// Erase stores of undef values. 315def erase_undef_store : GICombineRule< 316 (defs root:$root), 317 (match (wip_match_opcode G_STORE):$root, 318 [{ return Helper.matchUndefStore(*${root}); }]), 319 (apply [{ return Helper.eraseInst(*${root}); }]) 320>; 321 322def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">; 323def simplify_add_to_sub: GICombineRule < 324 (defs root:$root, simplify_add_to_sub_matchinfo:$info), 325 (match (wip_match_opcode G_ADD):$root, 326 [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]), 327 (apply [{ return Helper.applySimplifyAddToSub(*${root}, ${info});}]) 328>; 329 330// Fold fp_op(cst) to the constant result of the floating point operation. 331def constant_fp_op_matchinfo: GIDefMatchData<"Optional<APFloat>">; 332def constant_fp_op: GICombineRule < 333 (defs root:$root, constant_fp_op_matchinfo:$info), 334 (match (wip_match_opcode G_FNEG, G_FABS, G_FPTRUNC, G_FSQRT, G_FLOG2):$root, 335 [{ return Helper.matchCombineConstantFoldFpUnary(*${root}, ${info}); }]), 336 (apply [{ return Helper.applyCombineConstantFoldFpUnary(*${root}, ${info}); }]) 337>; 338 339// Fold int2ptr(ptr2int(x)) -> x 340def p2i_to_i2p_matchinfo: GIDefMatchData<"Register">; 341def p2i_to_i2p: GICombineRule< 342 (defs root:$root, p2i_to_i2p_matchinfo:$info), 343 (match (wip_match_opcode G_INTTOPTR):$root, 344 [{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]), 345 (apply [{ return Helper.applyCombineI2PToP2I(*${root}, ${info}); }]) 346>; 347 348// Fold ptr2int(int2ptr(x)) -> x 349def i2p_to_p2i_matchinfo: GIDefMatchData<"Register">; 350def i2p_to_p2i: GICombineRule< 351 (defs root:$root, i2p_to_p2i_matchinfo:$info), 352 (match (wip_match_opcode G_PTRTOINT):$root, 353 [{ return Helper.matchCombineP2IToI2P(*${root}, ${info}); }]), 354 (apply [{ return Helper.applyCombineP2IToI2P(*${root}, ${info}); }]) 355>; 356 357// Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y 358def add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair<Register, bool>">; 359def add_p2i_to_ptradd : GICombineRule< 360 (defs root:$root, add_p2i_to_ptradd_matchinfo:$info), 361 (match (wip_match_opcode G_ADD):$root, 362 [{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]), 363 (apply [{ return Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }]) 364>; 365 366// Fold (ptr_add (int2ptr C1), C2) -> C1 + C2 367def const_ptradd_to_i2p_matchinfo : GIDefMatchData<"int64_t">; 368def const_ptradd_to_i2p: GICombineRule< 369 (defs root:$root, const_ptradd_to_i2p_matchinfo:$info), 370 (match (wip_match_opcode G_PTR_ADD):$root, 371 [{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]), 372 (apply [{ return Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }]) 373>; 374 375// Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) 376def hoist_logic_op_with_same_opcode_hands: GICombineRule < 377 (defs root:$root, instruction_steps_matchdata:$info), 378 (match (wip_match_opcode G_AND, G_OR, G_XOR):$root, 379 [{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]), 380 (apply [{ return Helper.applyBuildInstructionSteps(*${root}, ${info});}]) 381>; 382 383// Fold ashr (shl x, C), C -> sext_inreg (C) 384def shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple<Register, int64_t>">; 385def shl_ashr_to_sext_inreg : GICombineRule< 386 (defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info), 387 (match (wip_match_opcode G_ASHR): $root, 388 [{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]), 389 (apply [{ return Helper.applyAshShlToSextInreg(*${root}, ${info});}]) 390>; 391// Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y. 392def redundant_and_matchinfo : GIDefMatchData<"Register">; 393def redundant_and: GICombineRule < 394 (defs root:$root, redundant_and_matchinfo:$matchinfo), 395 (match (wip_match_opcode G_AND):$root, 396 [{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]), 397 (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 398>; 399 400// Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y. 401def redundant_or_matchinfo : GIDefMatchData<"Register">; 402def redundant_or: GICombineRule < 403 (defs root:$root, redundant_or_matchinfo:$matchinfo), 404 (match (wip_match_opcode G_OR):$root, 405 [{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]), 406 (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 407>; 408 409// If the input is already sign extended, just drop the extension. 410// sext_inreg x, K -> 411// if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1) 412def redundant_sext_inreg: GICombineRule < 413 (defs root:$root), 414 (match (wip_match_opcode G_SEXT_INREG):$root, 415 [{ return Helper.matchRedundantSExtInReg(*${root}); }]), 416 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 417>; 418 419// Fold (anyext (trunc x)) -> x if the source type is same as 420// the destination type. 421def anyext_trunc_fold_matchinfo : GIDefMatchData<"Register">; 422def anyext_trunc_fold: GICombineRule < 423 (defs root:$root, anyext_trunc_fold_matchinfo:$matchinfo), 424 (match (wip_match_opcode G_ANYEXT):$root, 425 [{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]), 426 (apply [{ return Helper.applyCombineAnyExtTrunc(*${root}, ${matchinfo}); }]) 427>; 428 429// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x). 430def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">; 431def ext_ext_fold: GICombineRule < 432 (defs root:$root, ext_ext_fold_matchinfo:$matchinfo), 433 (match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root, 434 [{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]), 435 (apply [{ return Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }]) 436>; 437 438def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">; 439def not_cmp_fold : GICombineRule< 440 (defs root:$d, not_cmp_fold_matchinfo:$info), 441 (match (wip_match_opcode G_XOR): $d, 442 [{ return Helper.matchNotCmp(*${d}, ${info}); }]), 443 (apply [{ return Helper.applyNotCmp(*${d}, ${info}); }]) 444>; 445 446// Fold (fneg (fneg x)) -> x. 447def fneg_fneg_fold_matchinfo : GIDefMatchData<"Register">; 448def fneg_fneg_fold: GICombineRule < 449 (defs root:$root, fneg_fneg_fold_matchinfo:$matchinfo), 450 (match (wip_match_opcode G_FNEG):$root, 451 [{ return Helper.matchCombineFNegOfFNeg(*${root}, ${matchinfo}); }]), 452 (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 453>; 454 455// Fold (unmerge(merge x, y, z)) -> z, y, z. 456def unmerge_merge_matchinfo : GIDefMatchData<"SmallVector<Register, 8>">; 457def unmerge_merge : GICombineRule< 458 (defs root:$d, unmerge_merge_matchinfo:$info), 459 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 460 [{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]), 461 (apply [{ return Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]) 462>; 463 464// Fold (fabs (fabs x)) -> (fabs x). 465def fabs_fabs_fold_matchinfo : GIDefMatchData<"Register">; 466def fabs_fabs_fold: GICombineRule< 467 (defs root:$root, fabs_fabs_fold_matchinfo:$matchinfo), 468 (match (wip_match_opcode G_FABS):$root, 469 [{ return Helper.matchCombineFAbsOfFAbs(*${root}, ${matchinfo}); }]), 470 (apply [{ return Helper.applyCombineFAbsOfFAbs(*${root}, ${matchinfo}); }]) 471>; 472 473// Fold (unmerge cst) -> cst1, cst2, ... 474def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">; 475def unmerge_cst : GICombineRule< 476 (defs root:$d, unmerge_cst_matchinfo:$info), 477 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 478 [{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]), 479 (apply [{ return Helper.applyCombineUnmergeConstant(*${d}, ${info}); }]) 480>; 481 482// Transform x,y<dead> = unmerge z -> x = trunc z. 483def unmerge_dead_to_trunc : GICombineRule< 484 (defs root:$d), 485 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 486 [{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]), 487 (apply [{ return Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }]) 488>; 489 490// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0. 491def unmerge_zext_to_zext : GICombineRule< 492 (defs root:$d), 493 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 494 [{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]), 495 (apply [{ return Helper.applyCombineUnmergeZExtToZExt(*${d}); }]) 496>; 497 498// Fold trunc ([asz]ext x) -> x or ([asz]ext x) or (trunc x). 499def trunc_ext_fold_matchinfo : GIDefMatchData<"std::pair<Register, unsigned>">; 500def trunc_ext_fold: GICombineRule < 501 (defs root:$root, trunc_ext_fold_matchinfo:$matchinfo), 502 (match (wip_match_opcode G_TRUNC):$root, 503 [{ return Helper.matchCombineTruncOfExt(*${root}, ${matchinfo}); }]), 504 (apply [{ return Helper.applyCombineTruncOfExt(*${root}, ${matchinfo}); }]) 505>; 506 507// Fold trunc (shl x, K) -> shl (trunc x), K => K < VT.getScalarSizeInBits(). 508def trunc_shl_matchinfo : GIDefMatchData<"std::pair<Register, Register>">; 509def trunc_shl: GICombineRule < 510 (defs root:$root, trunc_shl_matchinfo:$matchinfo), 511 (match (wip_match_opcode G_TRUNC):$root, 512 [{ return Helper.matchCombineTruncOfShl(*${root}, ${matchinfo}); }]), 513 (apply [{ return Helper.applyCombineTruncOfShl(*${root}, ${matchinfo}); }]) 514>; 515 516// Transform (mul x, -1) -> (sub 0, x) 517def mul_by_neg_one: GICombineRule < 518 (defs root:$root), 519 (match (wip_match_opcode G_MUL):$root, 520 [{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]), 521 (apply [{ return Helper.applyCombineMulByNegativeOne(*${root}); }]) 522>; 523 524// Fold (xor (and x, y), y) -> (and (not x), y) 525def xor_of_and_with_same_reg_matchinfo : 526 GIDefMatchData<"std::pair<Register, Register>">; 527def xor_of_and_with_same_reg: GICombineRule < 528 (defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo), 529 (match (wip_match_opcode G_XOR):$root, 530 [{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]), 531 (apply [{ return Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }]) 532>; 533 534// Transform (ptr_add 0, x) -> (int_to_ptr x) 535def ptr_add_with_zero: GICombineRule< 536 (defs root:$root), 537 (match (wip_match_opcode G_PTR_ADD):$root, 538 [{ return Helper.matchPtrAddZero(*${root}); }]), 539 (apply [{ return Helper.applyPtrAddZero(*${root}); }])>; 540 541def regs_small_vec : GIDefMatchData<"SmallVector<Register, 4>">; 542def combine_insert_vec_elts_build_vector : GICombineRule< 543 (defs root:$root, regs_small_vec:$info), 544 (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root, 545 [{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]), 546 (apply [{ return Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>; 547 548def load_or_combine_matchdata : 549GIDefMatchData<"std::function<void(MachineIRBuilder &)>">; 550def load_or_combine : GICombineRule< 551 (defs root:$root, load_or_combine_matchdata:$info), 552 (match (wip_match_opcode G_OR):$root, 553 [{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]), 554 (apply [{ return Helper.applyLoadOrCombine(*${root}, ${info}); }])>; 555 556// Currently only the one combine above. 557def insert_vec_elt_combines : GICombineGroup< 558 [combine_insert_vec_elts_build_vector]>; 559 560// FIXME: These should use the custom predicate feature once it lands. 561def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, 562 undef_to_negative_one, 563 binop_left_undef_to_zero, 564 propagate_undef_any_op, 565 propagate_undef_all_ops, 566 propagate_undef_shuffle_mask, 567 erase_undef_store]>; 568 569def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, 570 binop_same_val, binop_left_to_zero, 571 binop_right_to_zero, p2i_to_i2p, 572 i2p_to_p2i, anyext_trunc_fold, 573 fneg_fneg_fold, right_identity_one]>; 574 575def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p]>; 576 577def known_bits_simplifications : GICombineGroup<[ 578 redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask]>; 579 580def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend]>; 581 582def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>; 583 584def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd, 585 mul_by_neg_one]>; 586 587def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, 588 ptr_add_immed_chain, combines_for_extload, combine_indexed_load_store, 589 undef_combines, identity_combines, simplify_add_to_sub, 590 hoist_logic_op_with_same_opcode_hands, 591 shl_ashr_to_sext_inreg, sext_inreg_of_load, 592 width_reduction_combines, select_combines, 593 known_bits_simplifications, ext_ext_fold, 594 not_cmp_fold, opt_brcond_by_inverting_cond, 595 unmerge_merge, fabs_fabs_fold, unmerge_cst, unmerge_dead_to_trunc, 596 unmerge_zext_to_zext, trunc_ext_fold, trunc_shl, 597 const_combines, xor_of_and_with_same_reg, ptr_add_with_zero, 598 shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine]>; 599