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 14//===----------------------------------------------------------------------===// 15// Base Classes 16// 17// These are the core classes that the combiner backend relies on. 18//===----------------------------------------------------------------------===// 19 20/// All arguments of the defs operator must be subclasses of GIDefKind or 21/// sub-dags whose operator is GIDefKindWithArgs. 22class GIDefKind; 23class GIDefKindWithArgs; 24 25/// Declare a root node. There must be at least one of these in every combine 26/// rule. 27def root : GIDefKind; 28 29def defs; 30 31def pattern; 32def match; 33def apply; 34 35def wip_match_opcode; 36 37// Common base class for GICombineRule and GICombineGroup. 38class GICombine { 39 // See GICombineGroup. We only declare it here to make the tablegen pass 40 // simpler. 41 list<GICombine> Rules = ?; 42} 43 44// A group of combine rules that can be added to a GICombiner or another group. 45class GICombineGroup<list<GICombine> rules> : GICombine { 46 // The rules contained in this group. The rules in a group are flattened into 47 // a single list and sorted into whatever order is most efficient. However, 48 // they will never be re-ordered such that behaviour differs from the 49 // specified order. It is therefore possible to use the order of rules in this 50 // list to describe priorities. 51 let Rules = rules; 52} 53 54// Declares a combiner implementation class 55class GICombiner<string classname, list<GICombine> rules> 56 : GICombineGroup<rules> { 57 // The class name to use in the generated output. 58 string Classname = classname; 59 // Combiners can use this so they're free to define tryCombineAll themselves 60 // and do extra work before/after calling the TableGen-erated code. 61 string CombineAllMethodName = "tryCombineAll"; 62} 63 64/// Declares data that is passed from the match stage to the apply stage. 65class GIDefMatchData<string type> { 66 /// A C++ type name indicating the storage type. 67 string Type = type; 68} 69 70class GICombineRule<dag defs, dag match, dag apply> : GICombine { 71 /// Defines the external interface of the match rule. This includes: 72 /// * The names of the root nodes (requires at least one) 73 /// See GIDefKind for details. 74 dag Defs = defs; 75 76 /// Defines the things which must be true for the pattern to match 77 dag Match = match; 78 79 /// Defines the things which happen after the decision is made to apply a 80 /// combine rule. 81 dag Apply = apply; 82 83 /// Defines the predicates that are checked before the match function 84 /// is called. Targets can use this to, for instance, check Subtarget 85 /// features. 86 list<Predicate> Predicates = []; 87 88 // Maximum number of permutations of this rule that can be emitted. 89 // Set to -1 to disable the limit. 90 int MaxPermutations = 16; 91} 92 93def gi_mo; 94def gi_imm; 95 96// This is an equivalent of PatFrags but for MIR Patterns. 97// 98// GICombinePatFrags can be used in place of instructions for 'match' patterns. 99// Much like normal instructions, the defs (outs) come first, and the ins second 100// 101// Out operands can only be of type "root" or "gi_mo", and they must be defined 102// by an instruction pattern in all alternatives. 103// 104// In operands can be gi_imm or gi_mo. They cannot be redefined in any alternative 105// pattern and may only appear in the C++ code, or in the output operand of an 106// instruction pattern. 107class GICombinePatFrag<dag outs, dag ins, list<dag> alts> { 108 dag InOperands = ins; 109 dag OutOperands = outs; 110 list<dag> Alternatives = alts; 111} 112 113//===----------------------------------------------------------------------===// 114// Pattern Special Types 115//===----------------------------------------------------------------------===// 116 117class GISpecialType; 118 119// In an apply pattern, GITypeOf can be used to set the type of a new temporary 120// register to match the type of a matched register. 121// 122// This can only be used on temporary registers defined by the apply pattern. 123// 124// TODO: Make this work in matchers as well? 125// 126// FIXME: Syntax is very ugly. 127class GITypeOf<string opName> : GISpecialType { 128 string OpName = opName; 129} 130 131// The type of an operand that can match a variable amount of operands. 132// This type contains a minimum and maximum number of operands to match. 133// The minimum must be 1 or more, as we cannot have an operand representing 134// zero operands, and the max can be zero (which means "unlimited") or a value 135// greater than the minimum. 136class GIVariadic<int min = 1, int max = 0> : GISpecialType { 137 int MinArgs = min; 138 int MaxArgs = max; 139} 140 141//===----------------------------------------------------------------------===// 142// Pattern Builtins 143//===----------------------------------------------------------------------===// 144 145// "Magic" Builtin instructions for MIR patterns. 146// The definitions that implement 147class GIBuiltinInst; 148 149// Replace all references to a register with another one. 150// 151// Usage: 152// (apply (GIReplaceReg $old, $new)) 153// 154// Operands: 155// - $old (out) register defined by a matched instruction 156// - $new (in) register 157// 158// Semantics: 159// - Can only appear in an 'apply' pattern. 160// - If both old/new are operands of matched instructions, 161// "canReplaceReg" is checked before applying the rule. 162def GIReplaceReg : GIBuiltinInst; 163 164// Apply action that erases the match root. 165// 166// Usage: 167// (apply (GIEraseRoot)) 168// 169// Semantics: 170// - Can only appear as the only pattern of an 'apply' pattern list. 171// - The root cannot have any output operands. 172// - The root must be a CodeGenInstruction 173// 174// TODO: Allow using this directly, like (apply GIEraseRoot) 175def GIEraseRoot : GIBuiltinInst; 176 177//===----------------------------------------------------------------------===// 178// Pattern MIFlags 179//===----------------------------------------------------------------------===// 180 181class MIFlagEnum<string enumName> { 182 string EnumName = "MachineInstr::" # enumName; 183} 184 185def FmNoNans : MIFlagEnum<"FmNoNans">; 186def FmNoInfs : MIFlagEnum<"FmNoInfs">; 187def FmNsz : MIFlagEnum<"FmNsz">; 188def FmArcp : MIFlagEnum<"FmArcp">; 189def FmContract : MIFlagEnum<"FmContract">; 190def FmAfn : MIFlagEnum<"FmAfn">; 191def FmReassoc : MIFlagEnum<"FmReassoc">; 192def IsExact : MIFlagEnum<"IsExact">; 193def NoSWrap : MIFlagEnum<"NoSWrap">; 194def NoUWrap : MIFlagEnum<"NoUWrap">; 195def NonNeg : MIFlagEnum<"NonNeg">; 196 197def MIFlags; 198// def not; -> Already defined as a SDNode 199 200//===----------------------------------------------------------------------===// 201 202def extending_load_matchdata : GIDefMatchData<"PreferredTuple">; 203def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">; 204def instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">; 205 206def register_matchinfo: GIDefMatchData<"Register">; 207def int64_matchinfo: GIDefMatchData<"int64_t">; 208def apint_matchinfo : GIDefMatchData<"APInt">; 209def constantfp_matchinfo : GIDefMatchData<"ConstantFP*">; 210def build_fn_matchinfo : 211GIDefMatchData<"std::function<void(MachineIRBuilder &)>">; 212def unsigned_matchinfo: GIDefMatchData<"unsigned">; 213 214def copy_prop : GICombineRule< 215 (defs root:$d), 216 (match (COPY $d, $s):$mi, 217 [{ return Helper.matchCombineCopy(*${mi}); }]), 218 (apply [{ Helper.applyCombineCopy(*${mi}); }])>; 219 220// idempotent operations 221// Fold (freeze (freeze x)) -> (freeze x). 222// Fold (fabs (fabs x)) -> (fabs x). 223// Fold (fcanonicalize (fcanonicalize x)) -> (fcanonicalize x). 224def idempotent_prop_frags : GICombinePatFrag< 225 (outs root:$dst, $src), (ins), 226 !foreach(op, [G_FREEZE, G_FABS, G_FCANONICALIZE], 227 (pattern (op $dst, $src), (op $src, $x)))>; 228 229def idempotent_prop : GICombineRule< 230 (defs root:$dst), 231 (match (idempotent_prop_frags $dst, $src)), 232 (apply (GIReplaceReg $dst, $src))>; 233 234// Convert freeze(Op(Op0, NonPoisonOps...)) to Op(freeze(Op0), NonPoisonOps...) 235// when Op0 is not guaranteed non-poison 236def push_freeze_to_prevent_poison_from_propagating : GICombineRule< 237 (defs root:$root, build_fn_matchinfo:$matchinfo), 238 (match (G_FREEZE $dst, $src):$root, 239 [{ return !isGuaranteedNotToBePoison(${src}.getReg(), MRI) && Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]), 240 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 241 242def extending_loads : GICombineRule< 243 (defs root:$root, extending_load_matchdata:$matchinfo), 244 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, 245 [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), 246 (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; 247 248def load_and_mask : GICombineRule< 249 (defs root:$root, build_fn_matchinfo:$matchinfo), 250 (match (wip_match_opcode G_AND):$root, 251 [{ return Helper.matchCombineLoadWithAndMask(*${root}, ${matchinfo}); }]), 252 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 253def combines_for_extload: GICombineGroup<[extending_loads, load_and_mask]>; 254 255def sext_trunc_sextload : GICombineRule< 256 (defs root:$d), 257 (match (wip_match_opcode G_SEXT_INREG):$d, 258 [{ return Helper.matchSextTruncSextLoad(*${d}); }]), 259 (apply [{ Helper.applySextTruncSextLoad(*${d}); }])>; 260 261def sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple<Register, unsigned>">; 262def sext_inreg_of_load : GICombineRule< 263 (defs root:$root, sext_inreg_of_load_matchdata:$matchinfo), 264 (match (wip_match_opcode G_SEXT_INREG):$root, 265 [{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]), 266 (apply [{ Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>; 267 268def sext_inreg_to_zext_inreg : GICombineRule< 269 (defs root:$dst), 270 (match 271 (G_SEXT_INREG $dst, $src, $imm):$root, 272 [{ 273 unsigned BitWidth = MRI.getType(${src}.getReg()).getScalarSizeInBits(); 274 return Helper.getKnownBits()->maskedValueIsZero(${src}.getReg(), 275 APInt::getOneBitSet(BitWidth, ${imm}.getImm() - 1)); }]), 276 (apply [{ 277 Helper.getBuilder().setInstrAndDebugLoc(*${root}); 278 Helper.getBuilder().buildZExtInReg(${dst}, ${src}, ${imm}.getImm()); 279 ${root}->eraseFromParent(); 280 }]) 281>; 282 283def combine_extracted_vector_load : GICombineRule< 284 (defs root:$root, build_fn_matchinfo:$matchinfo), 285 (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, 286 [{ return Helper.matchCombineExtractedVectorLoad(*${root}, ${matchinfo}); }]), 287 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 288 289def combine_indexed_load_store : GICombineRule< 290 (defs root:$root, indexed_load_store_matchdata:$matchinfo), 291 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, 292 [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), 293 (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; 294 295def opt_brcond_by_inverting_cond_matchdata : GIDefMatchData<"MachineInstr *">; 296def opt_brcond_by_inverting_cond : GICombineRule< 297 (defs root:$root, opt_brcond_by_inverting_cond_matchdata:$matchinfo), 298 (match (wip_match_opcode G_BR):$root, 299 [{ return Helper.matchOptBrCondByInvertingCond(*${root}, ${matchinfo}); }]), 300 (apply [{ Helper.applyOptBrCondByInvertingCond(*${root}, ${matchinfo}); }])>; 301 302def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; 303def ptr_add_immed_chain : GICombineRule< 304 (defs root:$d, ptr_add_immed_matchdata:$matchinfo), 305 (match (wip_match_opcode G_PTR_ADD):$d, 306 [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), 307 (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; 308 309def shift_const_op : GICombinePatFrag< 310 (outs root:$dst), (ins), 311 !foreach(op, 312 [G_SHL, G_ASHR, G_LSHR], 313 (pattern (op $dst, $shifted, $amt)))>; 314def shift_result_matchdata : GIDefMatchData<"std::optional<int64_t>">; 315def shifts_too_big : GICombineRule< 316 (defs root:$root, shift_result_matchdata:$matchinfo), 317 (match (shift_const_op $root):$mi, 318 [{ return Helper.matchShiftsTooBig(*${mi}, ${matchinfo}); }]), 319 (apply [{ 320 if (${matchinfo}) { 321 Helper.replaceInstWithConstant(*${mi}, *${matchinfo}); 322 } else { 323 Helper.replaceInstWithUndef(*${mi}); 324 } 325 }])>; 326 327// Fold shift (shift base x), y -> shift base, (x+y), if shifts are same 328def shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">; 329def shift_immed_chain : GICombineRule< 330 (defs root:$d, shift_immed_matchdata:$matchinfo), 331 (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d, 332 [{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]), 333 (apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>; 334 335// Transform shift (logic (shift X, C0), Y), C1 336// -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same 337def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">; 338def shift_of_shifted_logic_chain : GICombineRule< 339 (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo), 340 (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d, 341 [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]), 342 (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>; 343 344def mul_to_shl : GICombineRule< 345 (defs root:$d, unsigned_matchinfo:$matchinfo), 346 (match (G_MUL $d, $op1, $op2):$mi, 347 [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]), 348 (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>; 349 350// (sub x, C) -> (add x, -C) 351def sub_to_add : GICombineRule< 352 (defs root:$d, build_fn_matchinfo:$matchinfo), 353 (match (G_CONSTANT $c, $imm), 354 (G_SUB $d, $op1, $c):$mi, 355 [{ return Helper.matchCombineSubToAdd(*${mi}, ${matchinfo}); }]), 356 (apply [{ Helper.applyBuildFnNoErase(*${mi}, ${matchinfo}); }])>; 357 358// shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int 359def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">; 360def reduce_shl_of_extend : GICombineRule< 361 (defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo), 362 (match (G_SHL $dst, $src0, $src1):$mi, 363 [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]), 364 (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>; 365 366// Combine bitreverse(shl (bitreverse x), y)) -> (lshr x, y) 367def bitreverse_shl : GICombineRule< 368 (defs root:$d), 369 (match (G_BITREVERSE $rev, $val), 370 (G_SHL $src, $rev, $amt):$mi, 371 (G_BITREVERSE $d, $src), 372 [{ return Helper.isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, 373 {MRI.getType(${val}.getReg()), 374 MRI.getType(${amt}.getReg())}}); }]), 375 (apply (G_LSHR $d, $val, $amt))>; 376 377// Combine bitreverse(lshr (bitreverse x), y)) -> (shl x, y) 378def bitreverse_lshr : GICombineRule< 379 (defs root:$d), 380 (match (G_BITREVERSE $rev, $val), 381 (G_LSHR $src, $rev, $amt):$mi, 382 (G_BITREVERSE $d, $src), 383 [{ return Helper.isLegalOrBeforeLegalizer({TargetOpcode::G_SHL, 384 {MRI.getType(${val}.getReg()), 385 MRI.getType(${amt}.getReg())}}); }]), 386 (apply (G_SHL $d, $val, $amt))>; 387 388// Combine (shl (add x, c1), c2) -> (add (shl x, c2), c1 << c2) 389// Combine (shl (or x, c1), c2) -> (or (shl x, c2), c1 << c2) 390def commute_shift : GICombineRule< 391 (defs root:$d, build_fn_matchinfo:$matchinfo), 392 (match (wip_match_opcode G_SHL):$d, 393 [{ return Helper.matchCommuteShift(*${d}, ${matchinfo}); }]), 394 (apply [{ Helper.applyBuildFn(*${d}, ${matchinfo}); }])>; 395 396def narrow_binop_feeding_and : GICombineRule< 397 (defs root:$root, build_fn_matchinfo:$matchinfo), 398 (match (wip_match_opcode G_AND):$root, 399 [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]), 400 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; 401 402// [us]itofp(undef) = 0, because the result value is bounded. 403def undef_to_fp_zero : GICombineRule< 404 (defs root:$root), 405 (match (wip_match_opcode G_UITOFP, G_SITOFP):$root, 406 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 407 (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>; 408 409def undef_to_int_zero: GICombineRule< 410 (defs root:$root), 411 (match (wip_match_opcode G_AND, G_MUL):$root, 412 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 413 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 414 415def undef_to_negative_one: GICombineRule< 416 (defs root:$root), 417 (match (wip_match_opcode G_OR):$root, 418 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 419 (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>; 420 421def binop_left_undef_to_zero: GICombineRule< 422 (defs root:$root), 423 (match (wip_match_opcode G_SHL, G_UDIV, G_UREM):$root, 424 [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), 425 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 426 427def binop_right_undef_to_undef: GICombineRule< 428 (defs root:$root), 429 (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root, 430 [{ return Helper.matchOperandIsUndef(*${root}, 2); }]), 431 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 432 433def unary_undef_to_zero: GICombineRule< 434 (defs root:$root), 435 (match (wip_match_opcode G_ABS):$root, 436 [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), 437 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; 438 439def unary_undef_to_undef_frags : GICombinePatFrag< 440 (outs root:$dst), (ins), 441 !foreach(op, 442 [G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT, G_INTTOPTR, G_FPTOSI, 443 G_FPTOUI], 444 (pattern (op $dst, $x), (G_IMPLICIT_DEF $x)))>; 445def unary_undef_to_undef : GICombineRule< 446 (defs root:$dst), 447 (match (unary_undef_to_undef_frags $dst)), 448 (apply [{ Helper.replaceInstWithUndef(*${dst}.getParent()); }])>; 449 450// Instructions where if any source operand is undef, the instruction can be 451// replaced with undef. 452def propagate_undef_any_op: GICombineRule< 453 (defs root:$root), 454 (match (wip_match_opcode G_ADD, G_SUB, G_XOR):$root, 455 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), 456 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 457 458// Instructions where if all source operands are undef, the instruction can be 459// replaced with undef. 460def propagate_undef_all_ops: GICombineRule< 461 (defs root:$root), 462 (match (wip_match_opcode G_SHUFFLE_VECTOR, G_BUILD_VECTOR):$root, 463 [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]), 464 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 465 466// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF. 467def propagate_undef_shuffle_mask: GICombineRule< 468 (defs root:$root), 469 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 470 [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), 471 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 472 473// Replace a G_SHUFFLE_VECTOR with a G_EXTRACT_VECTOR_ELT. 474def shuffle_to_extract: GICombineRule< 475 (defs root:$root), 476 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 477 [{ return Helper.matchShuffleToExtract(*${root}); }]), 478 (apply [{ Helper.applyShuffleToExtract(*${root}); }])>; 479 480 // Replace an insert/extract element of an out of bounds index with undef. 481 def insert_extract_vec_elt_out_of_bounds : GICombineRule< 482 (defs root:$root), 483 (match (wip_match_opcode G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT):$root, 484 [{ return Helper.matchInsertExtractVecEltOutOfBounds(*${root}); }]), 485 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; 486 487// Fold (cond ? x : x) -> x 488def select_same_val: GICombineRule< 489 (defs root:$root), 490 (match (wip_match_opcode G_SELECT):$root, 491 [{ return Helper.matchSelectSameVal(*${root}); }]), 492 (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) 493>; 494 495// Fold (undef ? x : y) -> y 496def select_undef_cmp: GICombineRule< 497 (defs root:$dst), 498 (match (G_IMPLICIT_DEF $undef), 499 (G_SELECT $dst, $undef, $x, $y)), 500 (apply (GIReplaceReg $dst, $y)) 501>; 502 503// Fold (true ? x : y) -> x 504// Fold (false ? x : y) -> y 505def select_constant_cmp: GICombineRule< 506 (defs root:$root, unsigned_matchinfo:$matchinfo), 507 (match (wip_match_opcode G_SELECT):$root, 508 [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]), 509 (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }]) 510>; 511 512// Fold (C op x) -> (x op C) 513// TODO: handle more isCommutable opcodes 514// TODO: handle compares (currently not marked as isCommutable) 515def commute_int_constant_to_rhs : GICombineRule< 516 (defs root:$root), 517 (match (wip_match_opcode G_ADD, G_MUL, G_AND, G_OR, G_XOR, 518 G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_UADDO, G_SADDO, 519 G_UMULO, G_SMULO, G_UMULH, G_SMULH, 520 G_UADDSAT, G_SADDSAT, G_SMULFIX, G_UMULFIX, 521 G_SMULFIXSAT, G_UMULFIXSAT):$root, 522 [{ return Helper.matchCommuteConstantToRHS(*${root}); }]), 523 (apply [{ Helper.applyCommuteBinOpOperands(*${root}); }]) 524>; 525 526def commute_fp_constant_to_rhs : GICombineRule< 527 (defs root:$root), 528 (match (wip_match_opcode G_FADD, G_FMUL, G_FMINNUM, G_FMAXNUM, 529 G_FMINNUM_IEEE, G_FMAXNUM_IEEE, 530 G_FMINIMUM, G_FMAXIMUM):$root, 531 [{ return Helper.matchCommuteFPConstantToRHS(*${root}); }]), 532 (apply [{ Helper.applyCommuteBinOpOperands(*${root}); }]) 533>; 534 535def commute_constant_to_rhs : GICombineGroup<[ 536 commute_int_constant_to_rhs, 537 commute_fp_constant_to_rhs 538]>; 539 540// Fold x op 0 -> x 541def right_identity_zero_frags : GICombinePatFrag< 542 (outs root:$dst), (ins $x), 543 !foreach(op, 544 [G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, 545 G_LSHR, G_PTR_ADD, G_ROTL, G_ROTR], 546 (pattern (op $dst, $x, 0)))>; 547def right_identity_zero: GICombineRule< 548 (defs root:$dst), 549 (match (right_identity_zero_frags $dst, $lhs)), 550 (apply (GIReplaceReg $dst, $lhs)) 551>; 552 553def right_identity_neg_zero_fp: GICombineRule< 554 (defs root:$dst), 555 (match (G_FADD $dst, $x, $y):$root, 556 [{ return Helper.matchConstantFPOp(${y}, -0.0); }]), 557 (apply (GIReplaceReg $dst, $x)) 558>; 559 560// Fold x op 1 -> x 561def right_identity_one_int: GICombineRule< 562 (defs root:$dst), 563 (match (G_MUL $dst, $x, 1)), 564 (apply (GIReplaceReg $dst, $x)) 565>; 566 567def right_identity_one_fp: GICombineRule< 568 (defs root:$dst), 569 (match (G_FMUL $dst, $x, $y):$root, 570 [{ return Helper.matchConstantFPOp(${y}, 1.0); }]), 571 (apply (GIReplaceReg $dst, $x)) 572>; 573 574def right_identity_neg_one_fp: GICombineRule< 575 (defs root:$dst), 576 (match (G_FMUL $dst, $x, $y):$root, 577 [{ return Helper.matchConstantFPOp(${y}, -1.0); }]), 578 (apply (G_FNEG $dst, $x)) 579>; 580 581def right_identity_one : GICombineGroup<[right_identity_one_int, right_identity_one_fp]>; 582 583// Fold (x op x) - > x 584def binop_same_val_frags : GICombinePatFrag< 585 (outs root:$dst), (ins $x), 586 [ 587 (pattern (G_AND $dst, $x, $x)), 588 (pattern (G_OR $dst, $x, $x)), 589 ] 590>; 591def binop_same_val: GICombineRule< 592 (defs root:$dst), 593 (match (binop_same_val_frags $dst, $src)), 594 (apply (GIReplaceReg $dst, $src)) 595>; 596 597// Fold (0 op x) - > 0 598def binop_left_to_zero: GICombineRule< 599 (defs root:$root), 600 (match (wip_match_opcode G_SHL, G_LSHR, G_ASHR, G_SDIV, G_UDIV, G_SREM, 601 G_UREM):$root, 602 [{ return Helper.matchOperandIsZero(*${root}, 1); }]), 603 (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 604>; 605 606def urem_pow2_to_mask : GICombineRule< 607 (defs root:$root), 608 (match (wip_match_opcode G_UREM):$root, 609 [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]), 610 (apply [{ Helper.applySimplifyURemByPow2(*${root}); }]) 611>; 612 613// Push a binary operator through a select on constants. 614// 615// binop (select cond, K0, K1), K2 -> 616// select cond, (binop K0, K2), (binop K1, K2) 617 618// Every binary operator that has constant folding. We currently do 619// not have constant folding for G_FPOW, G_FMAXNUM_IEEE or 620// G_FMINNUM_IEEE. 621def fold_binop_into_select : GICombineRule< 622 (defs root:$root, unsigned_matchinfo:$select_op_no), 623 (match (wip_match_opcode 624 G_ADD, G_SUB, G_PTR_ADD, G_AND, G_OR, G_XOR, 625 G_SDIV, G_SREM, G_UDIV, G_UREM, G_LSHR, G_ASHR, G_SHL, 626 G_SMIN, G_SMAX, G_UMIN, G_UMAX, 627 G_FMUL, G_FADD, G_FSUB, G_FDIV, G_FREM, 628 G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root, 629 [{ return Helper.matchFoldBinOpIntoSelect(*${root}, ${select_op_no}); }]), 630 (apply [{ Helper.applyFoldBinOpIntoSelect(*${root}, ${select_op_no}); }]) 631>; 632 633// Transform d = [su]div(x, y) and r = [su]rem(x, y) - > d, r = [su]divrem(x, y) 634def div_rem_to_divrem_matchdata : GIDefMatchData<"MachineInstr *">; 635def div_rem_to_divrem : GICombineRule< 636 (defs root:$root, div_rem_to_divrem_matchdata:$matchinfo), 637 (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, 638 [{ return Helper.matchCombineDivRem(*${root}, ${matchinfo}); }]), 639 (apply [{ Helper.applyCombineDivRem(*${root}, ${matchinfo}); }]) 640>; 641 642// Fold (x op 0) - > 0 643def binop_right_to_zero: GICombineRule< 644 (defs root:$dst), 645 (match (G_MUL $dst, $lhs, 0:$zero)), 646 (apply (GIReplaceReg $dst, $zero)) 647>; 648 649// Erase stores of undef values. 650def erase_undef_store : GICombineRule< 651 (defs root:$root), 652 (match (wip_match_opcode G_STORE):$root, 653 [{ return Helper.matchUndefStore(*${root}); }]), 654 (apply [{ Helper.eraseInst(*${root}); }]) 655>; 656 657def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">; 658def simplify_add_to_sub: GICombineRule < 659 (defs root:$root, simplify_add_to_sub_matchinfo:$info), 660 (match (wip_match_opcode G_ADD):$root, 661 [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]), 662 (apply [{ Helper.applySimplifyAddToSub(*${root}, ${info});}]) 663>; 664 665// Fold fp_op(cst) to the constant result of the floating point operation. 666class constant_fold_unary_fp_op_rule<Instruction opcode> : GICombineRule < 667 (defs root:$dst), 668 (match (opcode $dst, $src0):$root, (G_FCONSTANT $src0, $cst)), 669 (apply [{ Helper.applyCombineConstantFoldFpUnary(*${root}, ${cst}.getFPImm()); }]) 670>; 671 672def constant_fold_fneg : constant_fold_unary_fp_op_rule<G_FNEG>; 673def constant_fold_fabs : constant_fold_unary_fp_op_rule<G_FABS>; 674def constant_fold_fsqrt : constant_fold_unary_fp_op_rule<G_FSQRT>; 675def constant_fold_flog2 : constant_fold_unary_fp_op_rule<G_FLOG2>; 676def constant_fold_fptrunc : constant_fold_unary_fp_op_rule<G_FPTRUNC>; 677 678// Fold constant zero int to fp conversions. 679class itof_const_zero_fold_rule<Instruction opcode> : GICombineRule < 680 (defs root:$dst), 681 (match (opcode $dst, 0)), 682 // Can't use COPY $dst, 0 here because the 0 operand may be a smaller type 683 // than the destination for itofp. 684 (apply [{ Helper.replaceInstWithFConstant(*${dst}.getParent(), 0.0); }]) 685>; 686def itof_const_zero_fold_si : itof_const_zero_fold_rule<G_SITOFP>; 687def itof_const_zero_fold_ui : itof_const_zero_fold_rule<G_UITOFP>; 688 689def constant_fold_fp_ops : GICombineGroup<[ 690 constant_fold_fneg, 691 constant_fold_fabs, 692 constant_fold_fsqrt, 693 constant_fold_flog2, 694 constant_fold_fptrunc, 695 itof_const_zero_fold_si, 696 itof_const_zero_fold_ui 697]>; 698 699// Fold int2ptr(ptr2int(x)) -> x 700def p2i_to_i2p: GICombineRule< 701 (defs root:$root, register_matchinfo:$info), 702 (match (wip_match_opcode G_INTTOPTR):$root, 703 [{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]), 704 (apply [{ Helper.applyCombineI2PToP2I(*${root}, ${info}); }]) 705>; 706 707// Fold ptr2int(int2ptr(x)) -> x 708def i2p_to_p2i: GICombineRule< 709 (defs root:$dst, register_matchinfo:$info), 710 (match (G_INTTOPTR $t, $ptr), 711 (G_PTRTOINT $dst, $t):$mi, 712 [{ ${info} = ${ptr}.getReg(); return true; }]), 713 (apply [{ Helper.applyCombineP2IToI2P(*${mi}, ${info}); }]) 714>; 715 716// Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y 717def add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair<Register, bool>">; 718def add_p2i_to_ptradd : GICombineRule< 719 (defs root:$root, add_p2i_to_ptradd_matchinfo:$info), 720 (match (wip_match_opcode G_ADD):$root, 721 [{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]), 722 (apply [{ Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }]) 723>; 724 725// Fold (ptr_add (int2ptr C1), C2) -> C1 + C2 726def const_ptradd_to_i2p: GICombineRule< 727 (defs root:$root, apint_matchinfo:$info), 728 (match (wip_match_opcode G_PTR_ADD):$root, 729 [{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]), 730 (apply [{ Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }]) 731>; 732 733// Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) 734def hoist_logic_op_with_same_opcode_hands: GICombineRule < 735 (defs root:$root, instruction_steps_matchdata:$info), 736 (match (wip_match_opcode G_AND, G_OR, G_XOR):$root, 737 [{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]), 738 (apply [{ Helper.applyBuildInstructionSteps(*${root}, ${info});}]) 739>; 740 741// Fold ashr (shl x, C), C -> sext_inreg (C) 742def shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple<Register, int64_t>">; 743def shl_ashr_to_sext_inreg : GICombineRule< 744 (defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info), 745 (match (wip_match_opcode G_ASHR): $root, 746 [{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]), 747 (apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}]) 748>; 749 750// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0 751def overlapping_and: GICombineRule < 752 (defs root:$root, build_fn_matchinfo:$info), 753 (match (wip_match_opcode G_AND):$root, 754 [{ return Helper.matchOverlappingAnd(*${root}, ${info}); }]), 755 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) 756>; 757 758// Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y. 759def redundant_and: GICombineRule < 760 (defs root:$root, register_matchinfo:$matchinfo), 761 (match (wip_match_opcode G_AND):$root, 762 [{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]), 763 (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 764>; 765 766// Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y. 767def redundant_or: GICombineRule < 768 (defs root:$root, register_matchinfo:$matchinfo), 769 (match (wip_match_opcode G_OR):$root, 770 [{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]), 771 (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 772>; 773 774// If the input is already sign extended, just drop the extension. 775// sext_inreg x, K -> 776// if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1) 777def redundant_sext_inreg: GICombineRule < 778 (defs root:$root), 779 (match (wip_match_opcode G_SEXT_INREG):$root, 780 [{ return Helper.matchRedundantSExtInReg(*${root}); }]), 781 (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) 782>; 783 784// Fold (anyext (trunc x)) -> x if the source type is same as 785// the destination type. 786def anyext_trunc_fold: GICombineRule < 787 (defs root:$root, register_matchinfo:$matchinfo), 788 (match (wip_match_opcode G_ANYEXT):$root, 789 [{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]), 790 (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 791>; 792 793// Fold (zext (trunc x)) -> x if the source type is same as the destination type 794// and truncated bits are known to be zero. 795def zext_trunc_fold: GICombineRule < 796 (defs root:$root, register_matchinfo:$matchinfo), 797 (match (wip_match_opcode G_ZEXT):$root, 798 [{ return Helper.matchCombineZextTrunc(*${root}, ${matchinfo}); }]), 799 (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) 800>; 801 802def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">; 803def not_cmp_fold : GICombineRule< 804 (defs root:$d, not_cmp_fold_matchinfo:$info), 805 (match (wip_match_opcode G_XOR): $d, 806 [{ return Helper.matchNotCmp(*${d}, ${info}); }]), 807 (apply [{ Helper.applyNotCmp(*${d}, ${info}); }]) 808>; 809 810// Fold (fneg (fneg x)) -> x. 811def fneg_fneg_fold: GICombineRule < 812 (defs root:$dst), 813 (match (G_FNEG $t, $src), 814 (G_FNEG $dst, $t)), 815 (apply (GIReplaceReg $dst, $src)) 816>; 817 818// Fold (unmerge(merge x, y, z)) -> z, y, z. 819def unmerge_merge_matchinfo : GIDefMatchData<"SmallVector<Register, 8>">; 820def unmerge_merge : GICombineRule< 821 (defs root:$d, unmerge_merge_matchinfo:$info), 822 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 823 [{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]), 824 (apply [{ Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]) 825>; 826 827// Fold merge(unmerge). 828def merge_unmerge : GICombineRule< 829 (defs root:$d, register_matchinfo:$matchinfo), 830 (match (wip_match_opcode G_MERGE_VALUES):$d, 831 [{ return Helper.matchCombineMergeUnmerge(*${d}, ${matchinfo}); }]), 832 (apply [{ Helper.replaceSingleDefInstWithReg(*${d}, ${matchinfo}); }]) 833>; 834 835// Fold (fabs (fneg x)) -> (fabs x). 836def fabs_fneg_fold: GICombineRule < 837 (defs root:$dst), 838 (match (G_FNEG $tmp, $x), 839 (G_FABS $dst, $tmp)), 840 (apply (G_FABS $dst, $x))>; 841 842// Fold (unmerge cst) -> cst1, cst2, ... 843def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">; 844def unmerge_cst : GICombineRule< 845 (defs root:$d, unmerge_cst_matchinfo:$info), 846 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 847 [{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]), 848 (apply [{ Helper.applyCombineUnmergeConstant(*${d}, ${info}); }]) 849>; 850 851// Fold (unmerge undef) -> undef, undef, ... 852def unmerge_undef : GICombineRule< 853 (defs root:$root, build_fn_matchinfo:$info), 854 (match (wip_match_opcode G_UNMERGE_VALUES): $root, 855 [{ return Helper.matchCombineUnmergeUndef(*${root}, ${info}); }]), 856 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) 857>; 858 859// Transform x,y<dead> = unmerge z -> x = trunc z. 860def unmerge_dead_to_trunc : GICombineRule< 861 (defs root:$d), 862 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 863 [{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]), 864 (apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }]) 865>; 866 867// Transform unmerge any build vector -> build vector anyext 868def unmerge_anyext_build_vector : GICombineRule< 869 (defs root:$root, build_fn_matchinfo:$matchinfo), 870 (match (wip_match_opcode G_UNMERGE_VALUES): $root, 871 [{ return Helper.matchUnmergeValuesAnyExtBuildVector(*${root}, ${matchinfo}); }]), 872 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }]) 873>; 874 875// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0. 876def unmerge_zext_to_zext : GICombineRule< 877 (defs root:$d), 878 (match (wip_match_opcode G_UNMERGE_VALUES): $d, 879 [{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]), 880 (apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }]) 881>; 882 883/// Transform merge_x_undef -> anyext. 884def merge_of_x_and_undef : GICombineRule < 885 (defs root:$root, build_fn_matchinfo:$matchinfo), 886 (match (G_IMPLICIT_DEF $undef), 887 (G_MERGE_VALUES $root, $x, $undef):$MI, 888 [{ return Helper.matchMergeXAndUndef(*${MI}, ${matchinfo}); }]), 889 (apply [{ Helper.applyBuildFn(*${MI}, ${matchinfo}); }])>; 890 891/// Transform merge_x_zero -> zext. 892def merge_of_x_and_zero : GICombineRule < 893 (defs root:$root, build_fn_matchinfo:$matchinfo), 894 (match (G_CONSTANT $zero, 0), 895 (G_MERGE_VALUES $root, $x, $zero):$MI, 896 [{ return Helper.matchMergeXAndZero(*${MI}, ${matchinfo}); }]), 897 (apply [{ Helper.applyBuildFn(*${MI}, ${matchinfo}); }])>; 898 899def merge_combines: GICombineGroup<[ 900 unmerge_anyext_build_vector, 901 unmerge_merge, 902 merge_unmerge, 903 unmerge_cst, 904 unmerge_undef, 905 unmerge_dead_to_trunc, 906 unmerge_zext_to_zext, 907 merge_of_x_and_undef, 908 merge_of_x_and_zero 909]>; 910 911// Under certain conditions, transform: 912// trunc (shl x, K) -> shl (trunc x), K// 913// trunc ([al]shr x, K) -> (trunc ([al]shr (trunc x), K)) 914def trunc_shift_matchinfo : GIDefMatchData<"std::pair<MachineInstr*, LLT>">; 915def trunc_shift: GICombineRule < 916 (defs root:$root, trunc_shift_matchinfo:$matchinfo), 917 (match (wip_match_opcode G_TRUNC):$root, 918 [{ return Helper.matchCombineTruncOfShift(*${root}, ${matchinfo}); }]), 919 (apply [{ Helper.applyCombineTruncOfShift(*${root}, ${matchinfo}); }]) 920>; 921 922// Transform (mul x, -1) -> (sub 0, x) 923def mul_by_neg_one: GICombineRule < 924 (defs root:$dst), 925 (match (G_MUL $dst, $x, -1)), 926 (apply (G_SUB $dst, 0, $x)) 927>; 928 929// Fold (xor (and x, y), y) -> (and (not x), y) 930def xor_of_and_with_same_reg_matchinfo : 931 GIDefMatchData<"std::pair<Register, Register>">; 932def xor_of_and_with_same_reg: GICombineRule < 933 (defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo), 934 (match (wip_match_opcode G_XOR):$root, 935 [{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]), 936 (apply [{ Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }]) 937>; 938 939// Transform (ptr_add 0, x) -> (int_to_ptr x) 940def ptr_add_with_zero: GICombineRule< 941 (defs root:$root), 942 (match (wip_match_opcode G_PTR_ADD):$root, 943 [{ return Helper.matchPtrAddZero(*${root}); }]), 944 (apply [{ Helper.applyPtrAddZero(*${root}); }])>; 945 946def regs_small_vec : GIDefMatchData<"SmallVector<Register, 4>">; 947def combine_insert_vec_elts_build_vector : GICombineRule< 948 (defs root:$root, regs_small_vec:$info), 949 (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root, 950 [{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]), 951 (apply [{ Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>; 952 953def load_or_combine : GICombineRule< 954 (defs root:$root, build_fn_matchinfo:$info), 955 (match (wip_match_opcode G_OR):$root, 956 [{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]), 957 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 958 959def extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">; 960def extend_through_phis : GICombineRule< 961 (defs root:$root, extend_through_phis_matchdata:$matchinfo), 962 (match (wip_match_opcode G_PHI):$root, 963 [{ return Helper.matchExtendThroughPhis(*${root}, ${matchinfo}); }]), 964 (apply [{ Helper.applyExtendThroughPhis(*${root}, ${matchinfo}); }])>; 965 966// Currently only the one combine above. 967def insert_vec_elt_combines : GICombineGroup< 968 [combine_insert_vec_elts_build_vector]>; 969 970def extract_vec_elt_build_vec : GICombineRule< 971 (defs root:$root, register_matchinfo:$matchinfo), 972 (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, 973 [{ return Helper.matchExtractVecEltBuildVec(*${root}, ${matchinfo}); }]), 974 (apply [{ Helper.applyExtractVecEltBuildVec(*${root}, ${matchinfo}); }])>; 975 976// Fold away full elt extracts from a build_vector. 977def extract_all_elts_from_build_vector_matchinfo : 978 GIDefMatchData<"SmallVector<std::pair<Register, MachineInstr*>>">; 979def extract_all_elts_from_build_vector : GICombineRule< 980 (defs root:$root, extract_all_elts_from_build_vector_matchinfo:$matchinfo), 981 (match (wip_match_opcode G_BUILD_VECTOR):$root, 982 [{ return Helper.matchExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }]), 983 (apply [{ Helper.applyExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }])>; 984 985def extract_vec_elt_combines : GICombineGroup<[ 986 extract_vec_elt_build_vec, 987 extract_all_elts_from_build_vector]>; 988 989def funnel_shift_from_or_shift : GICombineRule< 990 (defs root:$root, build_fn_matchinfo:$info), 991 (match (wip_match_opcode G_OR):$root, 992 [{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]), 993 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) 994>; 995 996def funnel_shift_to_rotate : GICombineRule< 997 (defs root:$root), 998 (match (wip_match_opcode G_FSHL, G_FSHR):$root, 999 [{ return Helper.matchFunnelShiftToRotate(*${root}); }]), 1000 (apply [{ Helper.applyFunnelShiftToRotate(*${root}); }]) 1001>; 1002 1003// Fold fshr x, y, 0 -> y 1004def funnel_shift_right_zero: GICombineRule< 1005 (defs root:$root), 1006 (match (G_FSHR $x, $y, $z, 0):$root), 1007 (apply (COPY $x, $z)) 1008>; 1009 1010// Fold fshl x, y, 0 -> x 1011def funnel_shift_left_zero: GICombineRule< 1012 (defs root:$root), 1013 (match (G_FSHL $x, $y, $z, 0):$root), 1014 (apply (COPY $x, $y)) 1015>; 1016 1017// Fold fsh(l/r) x, y, C -> fsh(l/r) x, y, C % bw 1018def funnel_shift_overshift: GICombineRule< 1019 (defs root:$root), 1020 (match (wip_match_opcode G_FSHL, G_FSHR):$root, 1021 [{ return Helper.matchConstantLargerBitWidth(*${root}, 3); }]), 1022 (apply [{ Helper.applyFunnelShiftConstantModulo(*${root}); }]) 1023>; 1024 1025def rotate_out_of_range : GICombineRule< 1026 (defs root:$root), 1027 (match (wip_match_opcode G_ROTR, G_ROTL):$root, 1028 [{ return Helper.matchRotateOutOfRange(*${root}); }]), 1029 (apply [{ Helper.applyRotateOutOfRange(*${root}); }]) 1030>; 1031 1032def icmp_to_true_false_known_bits : GICombineRule< 1033 (defs root:$d, int64_matchinfo:$matchinfo), 1034 (match (wip_match_opcode G_ICMP):$d, 1035 [{ return Helper.matchICmpToTrueFalseKnownBits(*${d}, ${matchinfo}); }]), 1036 (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; 1037 1038def icmp_to_lhs_known_bits : GICombineRule< 1039 (defs root:$root, build_fn_matchinfo:$info), 1040 (match (wip_match_opcode G_ICMP):$root, 1041 [{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]), 1042 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1043 1044def redundant_binop_in_equality : GICombineRule< 1045 (defs root:$root, build_fn_matchinfo:$info), 1046 (match (wip_match_opcode G_ICMP):$root, 1047 [{ return Helper.matchRedundantBinOpInEquality(*${root}, ${info}); }]), 1048 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1049 1050// Transform: (X == 0 & Y == 0) -> (X | Y) == 0 1051def double_icmp_zero_and_combine: GICombineRule< 1052 (defs root:$root), 1053 (match (G_ICMP $d1, $p, $s1, 0), 1054 (G_ICMP $d2, $p, $s2, 0), 1055 (G_AND $root, $d1, $d2), 1056 [{ return ${p}.getPredicate() == CmpInst::ICMP_EQ && 1057 !MRI.getType(${s1}.getReg()).getScalarType().isPointer() && 1058 (MRI.getType(${s1}.getReg()) == 1059 MRI.getType(${s2}.getReg())); }]), 1060 (apply (G_OR $ordst, $s1, $s2), 1061 (G_ICMP $root, $p, $ordst, 0)) 1062>; 1063 1064// Transform: (X != 0 | Y != 0) -> (X | Y) != 0 1065def double_icmp_zero_or_combine: GICombineRule< 1066 (defs root:$root), 1067 (match (G_ICMP $d1, $p, $s1, 0), 1068 (G_ICMP $d2, $p, $s2, 0), 1069 (G_OR $root, $d1, $d2), 1070 [{ return ${p}.getPredicate() == CmpInst::ICMP_NE && 1071 !MRI.getType(${s1}.getReg()).getScalarType().isPointer() && 1072 (MRI.getType(${s1}.getReg()) == 1073 MRI.getType(${s2}.getReg())); }]), 1074 (apply (G_OR $ordst, $s1, $s2), 1075 (G_ICMP $root, $p, $ordst, 0)) 1076>; 1077 1078def and_or_disjoint_mask : GICombineRule< 1079 (defs root:$root, build_fn_matchinfo:$info), 1080 (match (wip_match_opcode G_AND):$root, 1081 [{ return Helper.matchAndOrDisjointMask(*${root}, ${info}); }]), 1082 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${info}); }])>; 1083 1084def bitfield_extract_from_and : GICombineRule< 1085 (defs root:$root, build_fn_matchinfo:$info), 1086 (match (G_CONSTANT $mask, $imm2), 1087 (G_CONSTANT $lsb, $imm1), 1088 (G_LSHR $shift, $x, $lsb), 1089 (G_AND $root, $shift, $mask):$root, 1090 [{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]), 1091 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1092 1093def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift, 1094 funnel_shift_to_rotate, 1095 funnel_shift_right_zero, 1096 funnel_shift_left_zero, 1097 funnel_shift_overshift]>; 1098 1099def bitfield_extract_from_sext_inreg : GICombineRule< 1100 (defs root:$root, build_fn_matchinfo:$info), 1101 (match (wip_match_opcode G_SEXT_INREG):$root, 1102 [{ return Helper.matchBitfieldExtractFromSExtInReg(*${root}, ${info}); }]), 1103 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1104 1105def bitfield_extract_from_shr : GICombineRule< 1106 (defs root:$root, build_fn_matchinfo:$info), 1107 (match (wip_match_opcode G_ASHR, G_LSHR):$root, 1108 [{ return Helper.matchBitfieldExtractFromShr(*${root}, ${info}); }]), 1109 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1110 1111def bitfield_extract_from_shr_and : GICombineRule< 1112 (defs root:$root, build_fn_matchinfo:$info), 1113 (match (wip_match_opcode G_ASHR, G_LSHR):$root, 1114 [{ return Helper.matchBitfieldExtractFromShrAnd(*${root}, ${info}); }]), 1115 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1116 1117def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg, 1118 bitfield_extract_from_and, 1119 bitfield_extract_from_shr, 1120 bitfield_extract_from_shr_and]>; 1121 1122def udiv_by_const : GICombineRule< 1123 (defs root:$root), 1124 (match (wip_match_opcode G_UDIV):$root, 1125 [{ return Helper.matchUDivByConst(*${root}); }]), 1126 (apply [{ Helper.applyUDivByConst(*${root}); }])>; 1127 1128def sdiv_by_const : GICombineRule< 1129 (defs root:$root), 1130 (match (wip_match_opcode G_SDIV):$root, 1131 [{ return Helper.matchSDivByConst(*${root}); }]), 1132 (apply [{ Helper.applySDivByConst(*${root}); }])>; 1133 1134def sdiv_by_pow2 : GICombineRule< 1135 (defs root:$root), 1136 (match (G_SDIV $dst, $x, $y, (MIFlags (not IsExact))):$root, 1137 [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/true); }]), 1138 (apply [{ Helper.applySDivByPow2(*${root}); }])>; 1139 1140def udiv_by_pow2 : GICombineRule< 1141 (defs root:$root), 1142 (match (G_UDIV $dst, $x, $y, (MIFlags (not IsExact))):$root, 1143 [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/false); }]), 1144 (apply [{ Helper.applyUDivByPow2(*${root}); }])>; 1145 1146def intdiv_combines : GICombineGroup<[udiv_by_const, sdiv_by_const, 1147 sdiv_by_pow2, udiv_by_pow2]>; 1148 1149def reassoc_ptradd : GICombineRule< 1150 (defs root:$root, build_fn_matchinfo:$matchinfo), 1151 (match (wip_match_opcode G_PTR_ADD):$root, 1152 [{ return Helper.matchReassocPtrAdd(*${root}, ${matchinfo}); }]), 1153 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; 1154 1155def reassoc_comm_binops : GICombineRule< 1156 (defs root:$root, build_fn_matchinfo:$matchinfo), 1157 (match (G_ADD $root, $src1, $src2):$root, 1158 [{ return Helper.matchReassocCommBinOp(*${root}, ${matchinfo}); }]), 1159 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1160 1161def reassocs : GICombineGroup<[reassoc_ptradd, reassoc_comm_binops]>; 1162 1163// Constant fold operations. 1164def constant_fold_binop : GICombineRule< 1165 (defs root:$d, apint_matchinfo:$matchinfo), 1166 (match (wip_match_opcode G_ADD, G_PTR_ADD, G_AND, G_ASHR, G_LSHR, G_MUL, G_OR, 1167 G_SHL, G_SUB, G_XOR, G_UDIV, G_SDIV, G_UREM, G_SREM, 1168 G_SMIN, G_SMAX, G_UMIN, G_UMAX):$d, 1169 [{ return Helper.matchConstantFoldBinOp(*${d}, ${matchinfo}); }]), 1170 (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; 1171 1172def constant_fold_fp_binop : GICombineRule< 1173 (defs root:$d, constantfp_matchinfo:$matchinfo), 1174 (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV):$d, 1175 [{ return Helper.matchConstantFoldFPBinOp(*${d}, ${matchinfo}); }]), 1176 (apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>; 1177 1178 1179def constant_fold_fma : GICombineRule< 1180 (defs root:$d, constantfp_matchinfo:$matchinfo), 1181 (match (wip_match_opcode G_FMAD, G_FMA):$d, 1182 [{ return Helper.matchConstantFoldFMA(*${d}, ${matchinfo}); }]), 1183 (apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>; 1184 1185def constant_fold_cast_op : GICombineRule< 1186 (defs root:$d, apint_matchinfo:$matchinfo), 1187 (match (wip_match_opcode G_ZEXT, G_SEXT, G_ANYEXT):$d, 1188 [{ return Helper.matchConstantFoldCastOp(*${d}, ${matchinfo}); }]), 1189 (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; 1190 1191def mulo_by_2: GICombineRule< 1192 (defs root:$root, build_fn_matchinfo:$matchinfo), 1193 (match (wip_match_opcode G_UMULO, G_SMULO):$root, 1194 [{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]), 1195 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; 1196 1197def mulo_by_0: GICombineRule< 1198 (defs root:$root, build_fn_matchinfo:$matchinfo), 1199 (match (wip_match_opcode G_UMULO, G_SMULO):$root, 1200 [{ return Helper.matchMulOBy0(*${root}, ${matchinfo}); }]), 1201 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1202 1203// Transform (uadde x, y, 0) -> (uaddo x, y) 1204// (sadde x, y, 0) -> (saddo x, y) 1205// (usube x, y, 0) -> (usubo x, y) 1206// (ssube x, y, 0) -> (ssubo x, y) 1207def adde_to_addo: GICombineRule< 1208 (defs root:$root, build_fn_matchinfo:$matchinfo), 1209 (match (wip_match_opcode G_UADDE, G_SADDE, G_USUBE, G_SSUBE):$root, 1210 [{ return Helper.matchAddEToAddO(*${root}, ${matchinfo}); }]), 1211 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; 1212 1213def mulh_to_lshr : GICombineRule< 1214 (defs root:$root), 1215 (match (wip_match_opcode G_UMULH):$root, 1216 [{ return Helper.matchUMulHToLShr(*${root}); }]), 1217 (apply [{ Helper.applyUMulHToLShr(*${root}); }])>; 1218 1219def mulh_combines : GICombineGroup<[mulh_to_lshr]>; 1220 1221def redundant_neg_operands: GICombineRule< 1222 (defs root:$root, build_fn_matchinfo:$matchinfo), 1223 (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root, 1224 [{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]), 1225 (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; 1226 1227// Transform (fsub +-0.0, X) -> (fneg X) 1228def fsub_to_fneg: GICombineRule< 1229 (defs root:$root, register_matchinfo:$matchinfo), 1230 (match (wip_match_opcode G_FSUB):$root, 1231 [{ return Helper.matchFsubToFneg(*${root}, ${matchinfo}); }]), 1232 (apply [{ Helper.applyFsubToFneg(*${root}, ${matchinfo}); }])>; 1233 1234// Transform (fadd x, (fmul y, z)) -> (fma y, z, x) 1235// (fadd x, (fmul y, z)) -> (fmad y, z, x) 1236// Transform (fadd (fmul x, y), z) -> (fma x, y, z) 1237// (fadd (fmul x, y), z) -> (fmad x, y, z) 1238def combine_fadd_fmul_to_fmad_or_fma: GICombineRule< 1239 (defs root:$root, build_fn_matchinfo:$info), 1240 (match (wip_match_opcode G_FADD):$root, 1241 [{ return Helper.matchCombineFAddFMulToFMadOrFMA(*${root}, 1242 ${info}); }]), 1243 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1244 1245// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) 1246// -> (fmad (fpext x), (fpext y), z) 1247// Transform (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x) 1248// -> (fmad (fpext y), (fpext z), x) 1249def combine_fadd_fpext_fmul_to_fmad_or_fma: GICombineRule< 1250 (defs root:$root, build_fn_matchinfo:$info), 1251 (match (wip_match_opcode G_FADD):$root, 1252 [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMA(*${root}, 1253 ${info}); }]), 1254 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1255 1256// Transform (fadd (fma x, y, (fmul z, u)), v) -> (fma x, y, (fma z, u, v)) 1257// (fadd (fmad x, y, (fmul z, u)), v) -> (fmad x, y, (fmad z, u, v)) 1258// Transform (fadd v, (fma x, y, (fmul z, u))) -> (fma x, y, (fma z, u, v)) 1259// (fadd v, (fmad x, y, (fmul z, u))) -> (fmad x, y, (fmad z, u, v)) 1260def combine_fadd_fma_fmul_to_fmad_or_fma: GICombineRule< 1261 (defs root:$root, build_fn_matchinfo:$info), 1262 (match (wip_match_opcode G_FADD):$root, 1263 [{ return Helper.matchCombineFAddFMAFMulToFMadOrFMA(*${root}, 1264 ${info}); }]), 1265 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1266 1267// Transform (fadd (fma x, y, (fpext (fmul u, v))), z) -> 1268// (fma x, y, (fma (fpext u), (fpext v), z)) 1269def combine_fadd_fpext_fma_fmul_to_fmad_or_fma: GICombineRule< 1270 (defs root:$root, build_fn_matchinfo:$info), 1271 (match (wip_match_opcode G_FADD):$root, 1272 [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMAAggressive( 1273 *${root}, ${info}); }]), 1274 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1275 1276// Transform (fsub (fmul x, y), z) -> (fma x, y, -z) 1277// -> (fmad x, y, -z) 1278def combine_fsub_fmul_to_fmad_or_fma: GICombineRule< 1279 (defs root:$root, build_fn_matchinfo:$info), 1280 (match (wip_match_opcode G_FSUB):$root, 1281 [{ return Helper.matchCombineFSubFMulToFMadOrFMA(*${root}, 1282 ${info}); }]), 1283 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1284 1285// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) 1286// (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x) 1287def combine_fsub_fneg_fmul_to_fmad_or_fma: GICombineRule< 1288 (defs root:$root, build_fn_matchinfo:$info), 1289 (match (wip_match_opcode G_FSUB):$root, 1290 [{ return Helper.matchCombineFSubFNegFMulToFMadOrFMA(*${root}, 1291 ${info}); }]), 1292 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1293 1294// Transform (fsub (fpext (fmul x, y)), z) -> 1295// (fma (fpext x), (fpext y), (fneg z)) 1296def combine_fsub_fpext_fmul_to_fmad_or_fma: GICombineRule< 1297 (defs root:$root, build_fn_matchinfo:$info), 1298 (match (wip_match_opcode G_FSUB):$root, 1299 [{ return Helper.matchCombineFSubFpExtFMulToFMadOrFMA(*${root}, 1300 ${info}); }]), 1301 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1302 1303// Transform (fsub (fneg (fpext (fmul x, y))), z) -> 1304// (fneg (fma (fpext x), (fpext y), z)) 1305def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule< 1306 (defs root:$root, build_fn_matchinfo:$info), 1307 (match (wip_match_opcode G_FSUB):$root, 1308 [{ return Helper.matchCombineFSubFpExtFNegFMulToFMadOrFMA( 1309 *${root}, ${info}); }]), 1310 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1311 1312def combine_minmax_nan: GICombineRule< 1313 (defs root:$root, unsigned_matchinfo:$info), 1314 (match (wip_match_opcode G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root, 1315 [{ return Helper.matchCombineFMinMaxNaN(*${root}, ${info}); }]), 1316 (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${info}); }])>; 1317 1318// Transform (add x, (sub y, x)) -> y 1319// Transform (add (sub y, x), x) -> y 1320def add_sub_reg_frags : GICombinePatFrag< 1321 (outs root:$dst), (ins $src), 1322 [ 1323 (pattern (G_ADD $dst, $x, $tmp), (G_SUB $tmp, $src, $x)), 1324 (pattern (G_ADD $dst, $tmp, $x), (G_SUB $tmp, $src, $x)) 1325 ]>; 1326def add_sub_reg: GICombineRule < 1327 (defs root:$dst), 1328 (match (add_sub_reg_frags $dst, $src)), 1329 (apply (GIReplaceReg $dst, $src))>; 1330 1331def buildvector_identity_fold : GICombineRule< 1332 (defs root:$build_vector, register_matchinfo:$matchinfo), 1333 (match (wip_match_opcode G_BUILD_VECTOR_TRUNC, G_BUILD_VECTOR):$build_vector, 1334 [{ return Helper.matchBuildVectorIdentityFold(*${build_vector}, ${matchinfo}); }]), 1335 (apply [{ Helper.replaceSingleDefInstWithReg(*${build_vector}, ${matchinfo}); }])>; 1336 1337def trunc_buildvector_fold : GICombineRule< 1338 (defs root:$op, register_matchinfo:$matchinfo), 1339 (match (wip_match_opcode G_TRUNC):$op, 1340 [{ return Helper.matchTruncBuildVectorFold(*${op}, ${matchinfo}); }]), 1341 (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>; 1342 1343def trunc_lshr_buildvector_fold : GICombineRule< 1344 (defs root:$op, register_matchinfo:$matchinfo), 1345 (match (wip_match_opcode G_TRUNC):$op, 1346 [{ return Helper.matchTruncLshrBuildVectorFold(*${op}, ${matchinfo}); }]), 1347 (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>; 1348 1349// Transform: 1350// (x + y) - y -> x 1351// (x + y) - x -> y 1352// x - (y + x) -> 0 - y 1353// x - (x + z) -> 0 - z 1354def sub_add_reg: GICombineRule < 1355 (defs root:$root, build_fn_matchinfo:$matchinfo), 1356 (match (wip_match_opcode G_SUB):$root, 1357 [{ return Helper.matchSubAddSameReg(*${root}, ${matchinfo}); }]), 1358 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1359 1360def bitcast_bitcast_fold : GICombineRule< 1361 (defs root:$dst), 1362 (match (G_BITCAST $dst, $src1):$op, (G_BITCAST $src1, $src0), 1363 [{ return MRI.getType(${src0}.getReg()) == MRI.getType(${dst}.getReg()); }]), 1364 (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${src0}.getReg()); }])>; 1365 1366 1367def fptrunc_fpext_fold : GICombineRule< 1368 (defs root:$dst), 1369 (match (G_FPTRUNC $dst, $src1):$op, (G_FPEXT $src1, $src0), 1370 [{ return MRI.getType(${src0}.getReg()) == MRI.getType(${dst}.getReg()); }]), 1371 (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${src0}.getReg()); }])>; 1372 1373 1374def select_to_minmax: GICombineRule< 1375 (defs root:$root, build_fn_matchinfo:$info), 1376 (match (wip_match_opcode G_SELECT):$root, 1377 [{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]), 1378 (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; 1379 1380def select_to_iminmax: GICombineRule< 1381 (defs root:$root, build_fn_matchinfo:$info), 1382 (match (G_ICMP $tst, $tst1, $a, $b), 1383 (G_SELECT $root, $tst, $x, $y), 1384 [{ return Helper.matchSelectIMinMax(${root}, ${info}); }]), 1385 (apply [{ Helper.applyBuildFnMO(${root}, ${info}); }])>; 1386 1387def simplify_neg_minmax : GICombineRule< 1388 (defs root:$root, build_fn_matchinfo:$matchinfo), 1389 (match (wip_match_opcode G_SUB):$root, 1390 [{ return Helper.matchSimplifyNegMinMax(*${root}, ${matchinfo}); }]), 1391 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1392 1393def match_selects : GICombineRule< 1394 (defs root:$root, build_fn_matchinfo:$matchinfo), 1395 (match (wip_match_opcode G_SELECT):$root, 1396 [{ return Helper.matchSelect(*${root}, ${matchinfo}); }]), 1397 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1398 1399def match_ands : GICombineRule< 1400 (defs root:$root, build_fn_matchinfo:$matchinfo), 1401 (match (wip_match_opcode G_AND):$root, 1402 [{ return Helper.matchAnd(*${root}, ${matchinfo}); }]), 1403 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1404 1405def match_ors : GICombineRule< 1406 (defs root:$root, build_fn_matchinfo:$matchinfo), 1407 (match (wip_match_opcode G_OR):$root, 1408 [{ return Helper.matchOr(*${root}, ${matchinfo}); }]), 1409 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1410 1411def match_addos : GICombineRule< 1412 (defs root:$root, build_fn_matchinfo:$matchinfo), 1413 (match (wip_match_opcode G_SADDO, G_UADDO):$root, 1414 [{ return Helper.matchAddOverflow(*${root}, ${matchinfo}); }]), 1415 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1416 1417def match_subo_no_overflow : GICombineRule< 1418 (defs root:$root, build_fn_matchinfo:$matchinfo), 1419 (match (wip_match_opcode G_SSUBO, G_USUBO):$root, 1420 [{ return Helper.matchSuboCarryOut(*${root}, ${matchinfo}); }]), 1421 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1422 1423def match_extract_of_element_undef_vector: GICombineRule < 1424 (defs root:$root), 1425 (match (G_IMPLICIT_DEF $vector), 1426 (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), 1427 (apply (G_IMPLICIT_DEF $root)) 1428>; 1429 1430def match_extract_of_element_undef_index: GICombineRule < 1431 (defs root:$root), 1432 (match (G_IMPLICIT_DEF $idx), 1433 (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), 1434 (apply (G_IMPLICIT_DEF $root)) 1435>; 1436 1437def match_extract_of_element : GICombineRule< 1438 (defs root:$root, build_fn_matchinfo:$matchinfo), 1439 (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, 1440 [{ return Helper.matchExtractVectorElement(*${root}, ${matchinfo}); }]), 1441 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1442 1443def extract_vector_element_not_const : GICombineRule< 1444 (defs root:$root), 1445 (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx), 1446 (G_EXTRACT_VECTOR_ELT $root, $src, $idx)), 1447 (apply (GIReplaceReg $root, $value))>; 1448 1449def extract_vector_element_different_indices : GICombineRule< 1450 (defs root:$root, build_fn_matchinfo:$matchinfo), 1451 (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx2), 1452 (G_EXTRACT_VECTOR_ELT $root, $src, $idx1), 1453 [{ return Helper.matchExtractVectorElementWithDifferentIndices(${root}, ${matchinfo}); }]), 1454 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1455 1456def extract_vector_element_build_vector : GICombineRule< 1457 (defs root:$root, build_fn_matchinfo:$matchinfo), 1458 (match (G_CONSTANT $idx, $imm), 1459 (G_BUILD_VECTOR $src, GIVariadic<>:$unused):$Build, 1460 (G_EXTRACT_VECTOR_ELT $root, $src, $idx):$Extract, 1461 [{ return Helper.matchExtractVectorElementWithBuildVector(*${Extract}, *${Build}, 1462 ${matchinfo}); }]), 1463 (apply [{ Helper.applyBuildFn(*${Extract}, ${matchinfo}); }])>; 1464 1465def extract_vector_element_shuffle_vector : GICombineRule< 1466 (defs root:$root, build_fn_matchinfo:$matchinfo), 1467 (match (G_CONSTANT $idx, $imm), 1468 (G_SHUFFLE_VECTOR $src, $src1, $src2, $mask):$Shuffle, 1469 (G_EXTRACT_VECTOR_ELT $root, $src, $idx):$Extract, 1470 [{ return Helper.matchExtractVectorElementWithShuffleVector(*${Extract}, *${Shuffle}, 1471 ${matchinfo}); }]), 1472 (apply [{ Helper.applyBuildFn(*${Extract}, ${matchinfo}); }])>; 1473 1474def extract_vector_element_build_vector_trunc2 : GICombineRule< 1475 (defs root:$root, build_fn_matchinfo:$matchinfo), 1476 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y), 1477 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1478 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1479 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1480 1481def extract_vector_element_build_vector_trunc3 : GICombineRule< 1482 (defs root:$root, build_fn_matchinfo:$matchinfo), 1483 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z), 1484 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1485 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1486 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1487 1488def extract_vector_element_build_vector_trunc4 : GICombineRule< 1489 (defs root:$root, build_fn_matchinfo:$matchinfo), 1490 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a), 1491 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1492 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1493 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1494 1495def extract_vector_element_build_vector_trunc5 : GICombineRule< 1496 (defs root:$root, build_fn_matchinfo:$matchinfo), 1497 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b), 1498 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1499 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1500 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1501 1502def extract_vector_element_build_vector_trunc6 : GICombineRule< 1503 (defs root:$root, build_fn_matchinfo:$matchinfo), 1504 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c), 1505 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1506 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1507 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1508 1509def extract_vector_element_build_vector_trunc7 : GICombineRule< 1510 (defs root:$root, build_fn_matchinfo:$matchinfo), 1511 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d), 1512 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1513 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1514 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1515 1516def extract_vector_element_build_vector_trunc8 : GICombineRule< 1517 (defs root:$root, build_fn_matchinfo:$matchinfo), 1518 (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d, $e), 1519 (G_EXTRACT_VECTOR_ELT $root, $src, $idx), 1520 [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), 1521 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1522 1523def sext_trunc : GICombineRule< 1524 (defs root:$root, build_fn_matchinfo:$matchinfo), 1525 (match (G_TRUNC $src, $x, (MIFlags NoSWrap)), 1526 (G_SEXT $root, $src), 1527 [{ return Helper.matchSextOfTrunc(${root}, ${matchinfo}); }]), 1528 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1529 1530def zext_trunc : GICombineRule< 1531 (defs root:$root, build_fn_matchinfo:$matchinfo), 1532 (match (G_TRUNC $src, $x, (MIFlags NoUWrap)), 1533 (G_ZEXT $root, $src), 1534 [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]), 1535 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1536 1537def nneg_zext : GICombineRule< 1538 (defs root:$root, build_fn_matchinfo:$matchinfo), 1539 (match (G_ZEXT $root, $x, (MIFlags NonNeg)), 1540 [{ return Helper.matchNonNegZext(${root}, ${matchinfo}); }]), 1541 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1542 1543// Combines concat operations 1544def concat_matchinfo : GIDefMatchData<"SmallVector<Register>">; 1545def combine_concat_vector : GICombineRule< 1546 (defs root:$root, concat_matchinfo:$matchinfo), 1547 (match (wip_match_opcode G_CONCAT_VECTORS):$root, 1548 [{ return Helper.matchCombineConcatVectors(*${root}, ${matchinfo}); }]), 1549 (apply [{ Helper.applyCombineConcatVectors(*${root}, ${matchinfo}); }])>; 1550 1551// Combines Shuffles of Concats 1552// a = G_CONCAT_VECTORS x, y, undef, undef 1553// b = G_CONCAT_VECTORS z, undef, undef, undef 1554// c = G_SHUFFLE_VECTORS a, b, <0, 1, 4, undef> 1555// ===> 1556// c = G_CONCAT_VECTORS x, y, z, undef 1557def combine_shuffle_concat : GICombineRule< 1558 (defs root:$root, concat_matchinfo:$matchinfo), 1559 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 1560 [{ return Helper.matchCombineShuffleConcat(*${root}, ${matchinfo}); }]), 1561 (apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>; 1562 1563def insert_vector_element_idx_undef : GICombineRule< 1564 (defs root:$root), 1565 (match (G_IMPLICIT_DEF $idx), 1566 (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), 1567 (apply (G_IMPLICIT_DEF $root))>; 1568 1569def insert_vector_element_elt_undef : GICombineRule< 1570 (defs root:$root), 1571 (match (G_IMPLICIT_DEF $elt), 1572 (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx), 1573 [{ return isGuaranteedNotToBePoison(${src}.getReg(), MRI); }]), 1574 (apply (GIReplaceReg $root, $src))>; 1575 1576def insert_vector_element_extract_vector_element : GICombineRule< 1577 (defs root:$root), 1578 (match (G_EXTRACT_VECTOR_ELT $elt, $src, $idx), 1579 (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), 1580 (apply (GIReplaceReg $root, $src))>; 1581 1582def insert_vector_elt_oob : GICombineRule< 1583 (defs root:$root, build_fn_matchinfo:$matchinfo), 1584 (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root, 1585 [{ return Helper.matchInsertVectorElementOOB(*${root}, ${matchinfo}); }]), 1586 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1587 1588// Combine v8i8 (buildvector i8 (trunc(unmerge)), i8 (trunc), i8 (trunc), i8 (trunc), undef, undef, undef, undef) 1589def combine_use_vector_truncate : GICombineRule< 1590 (defs root:$root, register_matchinfo:$matchinfo), 1591 (match (G_BUILD_VECTOR $dst, GIVariadic<>:$unused):$root, 1592 [{ return Helper.matchUseVectorTruncate(*${root}, ${matchinfo}); }]), 1593 (apply [{ Helper.applyUseVectorTruncate(*${root}, ${matchinfo}); }])>; 1594 1595def add_of_vscale : GICombineRule< 1596 (defs root:$root, build_fn_matchinfo:$matchinfo), 1597 (match (G_VSCALE $left, $imm1), 1598 (G_VSCALE $right, $imm2), 1599 (G_ADD $root, $left, $right, (MIFlags NoSWrap)), 1600 [{ return Helper.matchAddOfVScale(${root}, ${matchinfo}); }]), 1601 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1602 1603def mul_of_vscale : GICombineRule< 1604 (defs root:$root, build_fn_matchinfo:$matchinfo), 1605 (match (G_VSCALE $left, $scale), 1606 (G_CONSTANT $x, $imm1), 1607 (G_MUL $root, $left, $x, (MIFlags NoSWrap)), 1608 [{ return Helper.matchMulOfVScale(${root}, ${matchinfo}); }]), 1609 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1610 1611def shl_of_vscale : GICombineRule< 1612 (defs root:$root, build_fn_matchinfo:$matchinfo), 1613 (match (G_VSCALE $left, $imm), 1614 (G_CONSTANT $x, $imm1), 1615 (G_SHL $root, $left, $x, (MIFlags NoSWrap)), 1616 [{ return Helper.matchShlOfVScale(${root}, ${matchinfo}); }]), 1617 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1618 1619def sub_of_vscale : GICombineRule< 1620 (defs root:$root, build_fn_matchinfo:$matchinfo), 1621 (match (G_VSCALE $right, $imm), 1622 (G_SUB $root, $x, $right, (MIFlags NoSWrap)), 1623 [{ return Helper.matchSubOfVScale(${root}, ${matchinfo}); }]), 1624 (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; 1625 1626def expand_const_fpowi : GICombineRule< 1627 (defs root:$root), 1628 (match (G_CONSTANT $int, $imm), 1629 (G_FPOWI $dst, $float, $int):$root, 1630 [{ return Helper.matchFPowIExpansion(*${root}, ${imm}.getCImm()->getSExtValue()); }]), 1631 (apply [{ Helper.applyExpandFPowI(*${root}, ${imm}.getCImm()->getSExtValue()); }])>; 1632 1633def combine_shuffle_undef_rhs : GICombineRule< 1634 (defs root:$root, build_fn_matchinfo:$matchinfo), 1635 (match (G_IMPLICIT_DEF $undef), 1636 (G_SHUFFLE_VECTOR $root, $src1, $undef, $mask):$root, 1637 [{ return Helper.matchShuffleUndefRHS(*${root}, ${matchinfo}); }]), 1638 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }]) 1639>; 1640 1641def combine_shuffle_disjoint_mask : GICombineRule< 1642 (defs root:$root, build_fn_matchinfo:$matchinfo), 1643 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, 1644 [{ return Helper.matchShuffleDisjointMask(*${root}, ${matchinfo}); }]), 1645 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }]) 1646>; 1647 1648// match_extract_of_element and insert_vector_elt_oob must be the first! 1649def vector_ops_combines: GICombineGroup<[ 1650match_extract_of_element_undef_vector, 1651match_extract_of_element_undef_index, 1652insert_vector_element_idx_undef, 1653insert_vector_element_elt_undef, 1654match_extract_of_element, 1655insert_vector_elt_oob, 1656extract_vector_element_not_const, 1657extract_vector_element_different_indices, 1658extract_vector_element_build_vector, 1659extract_vector_element_build_vector_trunc2, 1660extract_vector_element_build_vector_trunc3, 1661extract_vector_element_build_vector_trunc4, 1662extract_vector_element_build_vector_trunc5, 1663extract_vector_element_build_vector_trunc6, 1664extract_vector_element_build_vector_trunc7, 1665extract_vector_element_build_vector_trunc8, 1666extract_vector_element_shuffle_vector, 1667insert_vector_element_extract_vector_element, 1668add_of_vscale, 1669mul_of_vscale, 1670shl_of_vscale, 1671sub_of_vscale, 1672]>; 1673 1674 1675// fold ((0-A) + B) -> B-A 1676def ZeroMinusAPlusB : GICombineRule< 1677 (defs root:$root), 1678 (match (G_SUB $sub, 0, $A), 1679 (G_ADD $root, $sub, $B)), 1680 (apply (G_SUB $root, $B, $A))>; 1681 1682// fold (A + (0-B)) -> A-B 1683def APlusZeroMinusB : GICombineRule< 1684 (defs root:$root), 1685 (match (G_SUB $sub, 0, $B), 1686 (G_ADD $root, $A, $sub)), 1687 (apply (G_SUB $root, $A, $B))>; 1688 1689 // fold (A+(B-A)) -> B 1690 def APlusBMinusB : GICombineRule< 1691 (defs root:$root), 1692 (match (G_SUB $sub, $B, $A), 1693 (G_ADD $root, $A, $sub)), 1694 (apply (GIReplaceReg $root, $B))>; 1695 1696// fold ((B-A)+A) -> B 1697 def BMinusAPlusA : GICombineRule< 1698 (defs root:$root), 1699 (match (G_SUB $sub, $B, $A), 1700 (G_ADD $root, $sub, $A)), 1701 (apply (GIReplaceReg $root, $B))>; 1702 1703// fold ((A-B)+(C-A)) -> (C-B) 1704def AMinusBPlusCMinusA : GICombineRule< 1705 (defs root:$root), 1706 (match (G_SUB $sub1, $A, $B), 1707 (G_SUB $sub2, $C, $A), 1708 (G_ADD $root, $sub1, $sub2)), 1709 (apply (G_SUB $root, $C, $B))>; 1710 1711// fold ((A-B)+(B-C)) -> (A-C) 1712def AMinusBPlusBMinusC : GICombineRule< 1713 (defs root:$root), 1714 (match (G_SUB $sub1, $A, $B), 1715 (G_SUB $sub2, $B, $C), 1716 (G_ADD $root, $sub1, $sub2)), 1717 (apply (G_SUB $root, $A, $C))>; 1718 1719// fold (A+(B-(A+C))) to (B-C) 1720def APlusBMinusAplusC : GICombineRule< 1721 (defs root:$root), 1722 (match (G_ADD $add1, $A, $C), 1723 (G_SUB $sub1, $B, $add1), 1724 (G_ADD $root, $A, $sub1)), 1725 (apply (G_SUB $root, $B, $C))>; 1726 1727// fold (A+(B-(C+A))) to (B-C) 1728def APlusBMinusCPlusA : GICombineRule< 1729 (defs root:$root), 1730 (match (G_ADD $add1, $C, $A), 1731 (G_SUB $sub1, $B, $add1), 1732 (G_ADD $root, $A, $sub1)), 1733 (apply (G_SUB $root, $B, $C))>; 1734 1735// fold (A+C1)-C2 -> A+(C1-C2) 1736def APlusC1MinusC2: GICombineRule< 1737 (defs root:$root, build_fn_matchinfo:$matchinfo), 1738 (match (G_CONSTANT $c2, $imm2), 1739 (G_CONSTANT $c1, $imm1), 1740 (G_ADD $add, $A, $c1), 1741 (G_SUB $root, $add, $c2):$root, 1742 [{ return Helper.matchFoldAPlusC1MinusC2(*${root}, ${matchinfo}); }]), 1743 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1744 1745// fold C2-(A+C1) -> (C2-C1)-A 1746def C2MinusAPlusC1: GICombineRule< 1747 (defs root:$root, build_fn_matchinfo:$matchinfo), 1748 (match (G_CONSTANT $c2, $imm2), 1749 (G_CONSTANT $c1, $imm1), 1750 (G_ADD $add, $A, $c1), 1751 (G_SUB $root, $c2, $add):$root, 1752 [{ return Helper.matchFoldC2MinusAPlusC1(*${root}, ${matchinfo}); }]), 1753 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1754 1755// fold (A-C1)-C2 -> A-(C1+C2) 1756def AMinusC1MinusC2: GICombineRule< 1757 (defs root:$root, build_fn_matchinfo:$matchinfo), 1758 (match (G_CONSTANT $c2, $imm2), 1759 (G_CONSTANT $c1, $imm1), 1760 (G_SUB $sub1, $A, $c1), 1761 (G_SUB $root, $sub1, $c2):$root, 1762 [{ return Helper.matchFoldAMinusC1MinusC2(*${root}, ${matchinfo}); }]), 1763 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1764 1765// fold (C1-A)-C2 -> (C1-C2)-A 1766def C1Minus2MinusC2: GICombineRule< 1767 (defs root:$root, build_fn_matchinfo:$matchinfo), 1768 (match (G_CONSTANT $c2, $imm2), 1769 (G_CONSTANT $c1, $imm1), 1770 (G_SUB $sub1, $c1, $A), 1771 (G_SUB $root, $sub1, $c2):$root, 1772 [{ return Helper.matchFoldC1Minus2MinusC2(*${root}, ${matchinfo}); }]), 1773 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1774 1775// fold ((A-C1)+C2) -> (A+(C2-C1)) 1776def AMinusC1PlusC2: GICombineRule< 1777 (defs root:$root, build_fn_matchinfo:$matchinfo), 1778 (match (G_CONSTANT $c2, $imm2), 1779 (G_CONSTANT $c1, $imm1), 1780 (G_SUB $sub, $A, $c1), 1781 (G_ADD $root, $sub, $c2):$root, 1782 [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]), 1783 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1784 1785def integer_reassoc_combines: GICombineGroup<[ 1786 ZeroMinusAPlusB, 1787 APlusZeroMinusB, 1788 APlusBMinusB, 1789 BMinusAPlusA, 1790 AMinusBPlusCMinusA, 1791 AMinusBPlusBMinusC, 1792 APlusBMinusAplusC, 1793 APlusBMinusCPlusA, 1794 APlusC1MinusC2, 1795 C2MinusAPlusC1, 1796 AMinusC1MinusC2, 1797 C1Minus2MinusC2, 1798 AMinusC1PlusC2 1799]>; 1800 1801def freeze_of_non_undef_non_poison : GICombineRule< 1802 (defs root:$root), 1803 (match (G_FREEZE $root, $src), 1804 [{ return isGuaranteedNotToBeUndefOrPoison(${src}.getReg(), MRI); }]), 1805 (apply (GIReplaceReg $root, $src))>; 1806 1807def freeze_combines: GICombineGroup<[ 1808 freeze_of_non_undef_non_poison, 1809 push_freeze_to_prevent_poison_from_propagating 1810]>; 1811 1812/// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x). 1813class truncate_of_opcode<Instruction extOpcode> : GICombineRule < 1814 (defs root:$root, build_fn_matchinfo:$matchinfo), 1815 (match (extOpcode $ext, $src):$ExtMI, 1816 (G_TRUNC $root, $ext):$root, 1817 [{ return Helper.matchTruncateOfExt(*${root}, *${ExtMI}, ${matchinfo}); }]), 1818 (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; 1819 1820def truncate_of_zext : truncate_of_opcode<G_ZEXT>; 1821def truncate_of_sext : truncate_of_opcode<G_SEXT>; 1822def truncate_of_anyext : truncate_of_opcode<G_ANYEXT>; 1823 1824// Push cast through select. 1825class select_of_opcode<Instruction castOpcode> : GICombineRule < 1826 (defs root:$root, build_fn_matchinfo:$matchinfo), 1827 (match (G_SELECT $select, $cond, $true, $false):$Select, 1828 (castOpcode $root, $select):$Cast, 1829 [{ return Helper.matchCastOfSelect(*${Cast}, *${Select}, ${matchinfo}); }]), 1830 (apply [{ Helper.applyBuildFn(*${Cast}, ${matchinfo}); }])>; 1831 1832def select_of_zext : select_of_opcode<G_ZEXT>; 1833def select_of_anyext : select_of_opcode<G_ANYEXT>; 1834def select_of_truncate : select_of_opcode<G_TRUNC>; 1835 1836// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x). 1837class ext_of_ext_opcodes<Instruction ext1Opcode, Instruction ext2Opcode> : GICombineRule < 1838 (defs root:$root, build_fn_matchinfo:$matchinfo), 1839 (match (ext2Opcode $second, $src):$Second, 1840 (ext1Opcode $root, $second):$First, 1841 [{ return Helper.matchExtOfExt(*${First}, *${Second}, ${matchinfo}); }]), 1842 (apply [{ Helper.applyBuildFn(*${First}, ${matchinfo}); }])>; 1843 1844def zext_of_zext : ext_of_ext_opcodes<G_ZEXT, G_ZEXT>; 1845def zext_of_anyext : ext_of_ext_opcodes<G_ZEXT, G_ANYEXT>; 1846def sext_of_sext : ext_of_ext_opcodes<G_SEXT, G_SEXT>; 1847def sext_of_anyext : ext_of_ext_opcodes<G_SEXT, G_ANYEXT>; 1848def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>; 1849def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>; 1850def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>; 1851 1852// Push cast through build vector. 1853class buildvector_of_opcode<Instruction castOpcode> : GICombineRule < 1854 (defs root:$root, build_fn_matchinfo:$matchinfo), 1855 (match (G_BUILD_VECTOR $bv, GIVariadic<>:$unused):$Build, 1856 (castOpcode $root, $bv):$Cast, 1857 [{ return Helper.matchCastOfBuildVector(*${Cast}, *${Build}, ${matchinfo}); }]), 1858 (apply [{ Helper.applyBuildFn(*${Cast}, ${matchinfo}); }])>; 1859 1860def buildvector_of_truncate : buildvector_of_opcode<G_TRUNC>; 1861 1862// narrow binop. 1863// trunc (binop X, C) --> binop (trunc X, trunc C) 1864class narrow_binop_opcode<Instruction binopOpcode> : GICombineRule < 1865 (defs root:$root, build_fn_matchinfo:$matchinfo), 1866 (match (G_CONSTANT $const, $imm), 1867 (binopOpcode $binop, $x, $const):$Binop, 1868 (G_TRUNC $root, $binop):$Trunc, 1869 [{ return Helper.matchNarrowBinop(*${Trunc}, *${Binop}, ${matchinfo}); }]), 1870 (apply [{ Helper.applyBuildFn(*${Trunc}, ${matchinfo}); }])>; 1871 1872def narrow_binop_add : narrow_binop_opcode<G_ADD>; 1873def narrow_binop_sub : narrow_binop_opcode<G_SUB>; 1874def narrow_binop_mul : narrow_binop_opcode<G_MUL>; 1875def narrow_binop_and : narrow_binop_opcode<G_AND>; 1876def narrow_binop_or : narrow_binop_opcode<G_OR>; 1877def narrow_binop_xor : narrow_binop_opcode<G_XOR>; 1878 1879// Cast of integer. 1880class integer_of_opcode<Instruction castOpcode> : GICombineRule < 1881 (defs root:$root, apint_matchinfo:$matchinfo), 1882 (match (G_CONSTANT $int, $imm), 1883 (castOpcode $root, $int):$Cast, 1884 [{ return Helper.matchCastOfInteger(*${Cast}, ${matchinfo}); }]), 1885 (apply [{ Helper.replaceInstWithConstant(*${Cast}, ${matchinfo}); }])>; 1886 1887def integer_of_truncate : integer_of_opcode<G_TRUNC>; 1888 1889def cast_of_cast_combines: GICombineGroup<[ 1890 truncate_of_zext, 1891 truncate_of_sext, 1892 truncate_of_anyext, 1893 zext_of_zext, 1894 zext_of_anyext, 1895 sext_of_sext, 1896 sext_of_anyext, 1897 anyext_of_anyext, 1898 anyext_of_zext, 1899 anyext_of_sext 1900]>; 1901 1902def cast_combines: GICombineGroup<[ 1903 cast_of_cast_combines, 1904 select_of_zext, 1905 select_of_anyext, 1906 select_of_truncate, 1907 buildvector_of_truncate, 1908 narrow_binop_add, 1909 narrow_binop_sub, 1910 narrow_binop_mul, 1911 narrow_binop_and, 1912 narrow_binop_or, 1913 narrow_binop_xor, 1914 integer_of_truncate 1915]>; 1916 1917def canonicalize_icmp : GICombineRule< 1918 (defs root:$root, build_fn_matchinfo:$matchinfo), 1919 (match (G_ICMP $root, $pred, $lhs, $rhs):$cmp, 1920 [{ return Helper.matchCanonicalizeICmp(*${cmp}, ${matchinfo}); }]), 1921 (apply [{ Helper.applyBuildFn(*${cmp}, ${matchinfo}); }])>; 1922 1923def canonicalize_fcmp : GICombineRule< 1924 (defs root:$root, build_fn_matchinfo:$matchinfo), 1925 (match (G_FCMP $root, $pred, $lhs, $rhs):$cmp, 1926 [{ return Helper.matchCanonicalizeFCmp(*${cmp}, ${matchinfo}); }]), 1927 (apply [{ Helper.applyBuildFn(*${cmp}, ${matchinfo}); }])>; 1928 1929def cmp_combines: GICombineGroup<[ 1930 canonicalize_icmp, 1931 canonicalize_fcmp, 1932 icmp_to_true_false_known_bits, 1933 icmp_to_lhs_known_bits, 1934 double_icmp_zero_and_combine, 1935 double_icmp_zero_or_combine, 1936 redundant_binop_in_equality 1937]>; 1938 1939 1940def overflow_combines: GICombineGroup<[ 1941 match_addos, 1942 match_subo_no_overflow 1943]>; 1944 1945// FIXME: These should use the custom predicate feature once it lands. 1946def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, 1947 undef_to_negative_one, 1948 binop_left_undef_to_zero, 1949 binop_right_undef_to_undef, 1950 unary_undef_to_zero, 1951 unary_undef_to_undef, 1952 propagate_undef_any_op, 1953 propagate_undef_all_ops, 1954 propagate_undef_shuffle_mask, 1955 erase_undef_store, 1956 insert_extract_vec_elt_out_of_bounds]>; 1957 1958def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, 1959 binop_same_val, binop_left_to_zero, 1960 binop_right_to_zero, p2i_to_i2p, 1961 i2p_to_p2i, anyext_trunc_fold, 1962 fneg_fneg_fold, right_identity_one, 1963 add_sub_reg, buildvector_identity_fold, 1964 trunc_buildvector_fold, 1965 trunc_lshr_buildvector_fold, 1966 bitcast_bitcast_fold, fptrunc_fpext_fold, 1967 right_identity_neg_zero_fp, 1968 right_identity_neg_one_fp]>; 1969 1970def const_combines : GICombineGroup<[constant_fold_fp_ops, const_ptradd_to_i2p, 1971 overlapping_and, mulo_by_2, mulo_by_0, 1972 adde_to_addo, 1973 combine_minmax_nan, expand_const_fpowi]>; 1974 1975def known_bits_simplifications : GICombineGroup<[ 1976 redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask, 1977 zext_trunc_fold, 1978 sext_inreg_to_zext_inreg]>; 1979 1980def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend, 1981 narrow_binop_feeding_and]>; 1982 1983def phi_combines : GICombineGroup<[extend_through_phis]>; 1984 1985def bitreverse_shift : GICombineGroup<[bitreverse_shl, bitreverse_lshr]>; 1986 1987def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp, 1988 select_to_iminmax, match_selects]>; 1989 1990def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, sub_to_add, 1991 add_p2i_to_ptradd, mul_by_neg_one, 1992 idempotent_prop]>; 1993 1994def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, 1995 combine_fadd_fpext_fmul_to_fmad_or_fma, combine_fadd_fma_fmul_to_fmad_or_fma, 1996 combine_fadd_fpext_fma_fmul_to_fmad_or_fma, combine_fsub_fmul_to_fmad_or_fma, 1997 combine_fsub_fneg_fmul_to_fmad_or_fma, combine_fsub_fpext_fmul_to_fmad_or_fma, 1998 combine_fsub_fpext_fneg_fmul_to_fmad_or_fma]>; 1999 2000def constant_fold_binops : GICombineGroup<[constant_fold_binop, 2001 constant_fold_fp_binop]>; 2002 2003def prefer_sign_combines : GICombineGroup<[nneg_zext]>; 2004 2005def shuffle_combines : GICombineGroup<[combine_shuffle_concat, 2006 combine_shuffle_undef_rhs, 2007 combine_shuffle_disjoint_mask]>; 2008 2009def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines, 2010 vector_ops_combines, freeze_combines, cast_combines, 2011 insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload, 2012 combine_extracted_vector_load, 2013 undef_combines, identity_combines, phi_combines, 2014 simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big, 2015 reassocs, ptr_add_immed_chain, cmp_combines, 2016 shl_ashr_to_sext_inreg, sext_inreg_of_load, 2017 width_reduction_combines, select_combines, 2018 known_bits_simplifications, trunc_shift, 2019 not_cmp_fold, opt_brcond_by_inverting_cond, 2020 const_combines, xor_of_and_with_same_reg, ptr_add_with_zero, 2021 shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine, 2022 div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift, 2023 form_bitfield_extract, constant_fold_binops, constant_fold_fma, 2024 constant_fold_cast_op, fabs_fneg_fold, 2025 intdiv_combines, mulh_combines, redundant_neg_operands, 2026 and_or_disjoint_mask, fma_combines, fold_binop_into_select, 2027 sub_add_reg, select_to_minmax, 2028 fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors, 2029 simplify_neg_minmax, combine_concat_vector, 2030 sext_trunc, zext_trunc, prefer_sign_combines, shuffle_combines, 2031 combine_use_vector_truncate, merge_combines, overflow_combines]>; 2032 2033// A combine group used to for prelegalizer combiners at -O0. The combines in 2034// this group have been selected based on experiments to balance code size and 2035// compile time performance. 2036def optnone_combines : GICombineGroup<[trivial_combines, 2037 ptr_add_immed_chain, combines_for_extload, 2038 not_cmp_fold, opt_brcond_by_inverting_cond, combine_concat_vector]>; 2039