1 //===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===// 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 /// \file 9 /// This contains common combine transformations that may be used in a combine 10 /// pass,or by the target elsewhere. 11 /// Targets can pick individual opcode transformations from the helper or use 12 /// tryCombine which invokes all transformations. All of the transformations 13 /// return true if the MachineInstruction changed and false otherwise. 14 /// 15 //===--------------------------------------------------------------------===// 16 17 #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H 18 #define LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H 19 20 #include "llvm/ADT/APFloat.h" 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/CodeGen/LowLevelType.h" 23 #include "llvm/CodeGen/Register.h" 24 #include "llvm/Support/Alignment.h" 25 26 namespace llvm { 27 28 class GISelChangeObserver; 29 class MachineIRBuilder; 30 class MachineInstrBuilder; 31 class MachineRegisterInfo; 32 class MachineInstr; 33 class MachineOperand; 34 class GISelKnownBits; 35 class MachineDominatorTree; 36 class LegalizerInfo; 37 struct LegalityQuery; 38 class TargetLowering; 39 40 struct PreferredTuple { 41 LLT Ty; // The result type of the extend. 42 unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT 43 MachineInstr *MI; 44 }; 45 46 struct IndexedLoadStoreMatchInfo { 47 Register Addr; 48 Register Base; 49 Register Offset; 50 bool IsPre; 51 }; 52 53 struct PtrAddChain { 54 int64_t Imm; 55 Register Base; 56 }; 57 58 struct RegisterImmPair { 59 Register Reg; 60 int64_t Imm; 61 }; 62 63 struct ShiftOfShiftedLogic { 64 MachineInstr *Logic; 65 MachineInstr *Shift2; 66 Register LogicNonShiftReg; 67 uint64_t ValSum; 68 }; 69 70 using OperandBuildSteps = 71 SmallVector<std::function<void(MachineInstrBuilder &)>, 4>; 72 struct InstructionBuildSteps { 73 unsigned Opcode = 0; /// The opcode for the produced instruction. 74 OperandBuildSteps OperandFns; /// Operands to be added to the instruction. 75 InstructionBuildSteps() = default; InstructionBuildStepsInstructionBuildSteps76 InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns) 77 : Opcode(Opcode), OperandFns(OperandFns) {} 78 }; 79 80 struct InstructionStepsMatchInfo { 81 /// Describes instructions to be built during a combine. 82 SmallVector<InstructionBuildSteps, 2> InstrsToBuild; 83 InstructionStepsMatchInfo() = default; InstructionStepsMatchInfoInstructionStepsMatchInfo84 InstructionStepsMatchInfo( 85 std::initializer_list<InstructionBuildSteps> InstrsToBuild) 86 : InstrsToBuild(InstrsToBuild) {} 87 }; 88 89 class CombinerHelper { 90 protected: 91 MachineIRBuilder &Builder; 92 MachineRegisterInfo &MRI; 93 GISelChangeObserver &Observer; 94 GISelKnownBits *KB; 95 MachineDominatorTree *MDT; 96 const LegalizerInfo *LI; 97 98 public: 99 CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, 100 GISelKnownBits *KB = nullptr, 101 MachineDominatorTree *MDT = nullptr, 102 const LegalizerInfo *LI = nullptr); 103 getKnownBits()104 GISelKnownBits *getKnownBits() const { 105 return KB; 106 } 107 108 const TargetLowering &getTargetLowering() const; 109 110 /// \return true if the combine is running prior to legalization, or if \p 111 /// Query is legal on the target. 112 bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const; 113 114 /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes 115 void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const; 116 117 /// Replace a single register operand with a new register and inform the 118 /// observer of the changes. 119 void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, 120 Register ToReg) const; 121 122 /// If \p MI is COPY, try to combine it. 123 /// Returns true if MI changed. 124 bool tryCombineCopy(MachineInstr &MI); 125 bool matchCombineCopy(MachineInstr &MI); 126 void applyCombineCopy(MachineInstr &MI); 127 128 /// Returns true if \p DefMI precedes \p UseMI or they are the same 129 /// instruction. Both must be in the same basic block. 130 bool isPredecessor(const MachineInstr &DefMI, const MachineInstr &UseMI); 131 132 /// Returns true if \p DefMI dominates \p UseMI. By definition an 133 /// instruction dominates itself. 134 /// 135 /// If we haven't been provided with a MachineDominatorTree during 136 /// construction, this function returns a conservative result that tracks just 137 /// a single basic block. 138 bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI); 139 140 /// If \p MI is extend that consumes the result of a load, try to combine it. 141 /// Returns true if MI changed. 142 bool tryCombineExtendingLoads(MachineInstr &MI); 143 bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); 144 void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); 145 146 /// Combine \p MI into a pre-indexed or post-indexed load/store operation if 147 /// legal and the surrounding code makes it useful. 148 bool tryCombineIndexedLoadStore(MachineInstr &MI); 149 bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); 150 void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo); 151 152 bool matchSextTruncSextLoad(MachineInstr &MI); 153 bool applySextTruncSextLoad(MachineInstr &MI); 154 155 /// Match sext_inreg(load p), imm -> sextload p 156 bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo); 157 bool applySextInRegOfLoad(MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo); 158 159 /// Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM 160 /// when their source operands are identical. 161 bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI); 162 void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI); 163 164 /// If a brcond's true block is not the fallthrough, make it so by inverting 165 /// the condition and swapping operands. 166 bool matchOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond); 167 void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond); 168 169 /// If \p MI is G_CONCAT_VECTORS, try to combine it. 170 /// Returns true if MI changed. 171 /// Right now, we support: 172 /// - concat_vector(undef, undef) => undef 173 /// - concat_vector(build_vector(A, B), build_vector(C, D)) => 174 /// build_vector(A, B, C, D) 175 /// 176 /// \pre MI.getOpcode() == G_CONCAT_VECTORS. 177 bool tryCombineConcatVectors(MachineInstr &MI); 178 /// Check if the G_CONCAT_VECTORS \p MI is undef or if it 179 /// can be flattened into a build_vector. 180 /// In the first case \p IsUndef will be true. 181 /// In the second case \p Ops will contain the operands needed 182 /// to produce the flattened build_vector. 183 /// 184 /// \pre MI.getOpcode() == G_CONCAT_VECTORS. 185 bool matchCombineConcatVectors(MachineInstr &MI, bool &IsUndef, 186 SmallVectorImpl<Register> &Ops); 187 /// Replace \p MI with a flattened build_vector with \p Ops or an 188 /// implicit_def if IsUndef is true. 189 void applyCombineConcatVectors(MachineInstr &MI, bool IsUndef, 190 const ArrayRef<Register> Ops); 191 192 /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS. 193 /// Returns true if MI changed. 194 /// 195 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR. 196 bool tryCombineShuffleVector(MachineInstr &MI); 197 /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a 198 /// concat_vectors. 199 /// \p Ops will contain the operands needed to produce the flattened 200 /// concat_vectors. 201 /// 202 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR. 203 bool matchCombineShuffleVector(MachineInstr &MI, 204 SmallVectorImpl<Register> &Ops); 205 /// Replace \p MI with a concat_vectors with \p Ops. 206 void applyCombineShuffleVector(MachineInstr &MI, 207 const ArrayRef<Register> Ops); 208 209 /// Optimize memcpy intrinsics et al, e.g. constant len calls. 210 /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline. 211 /// 212 /// For example (pre-indexed): 213 /// 214 /// $addr = G_PTR_ADD $base, $offset 215 /// [...] 216 /// $val = G_LOAD $addr 217 /// [...] 218 /// $whatever = COPY $addr 219 /// 220 /// --> 221 /// 222 /// $val, $addr = G_INDEXED_LOAD $base, $offset, 1 (IsPre) 223 /// [...] 224 /// $whatever = COPY $addr 225 /// 226 /// or (post-indexed): 227 /// 228 /// G_STORE $val, $base 229 /// [...] 230 /// $addr = G_PTR_ADD $base, $offset 231 /// [...] 232 /// $whatever = COPY $addr 233 /// 234 /// --> 235 /// 236 /// $addr = G_INDEXED_STORE $val, $base, $offset 237 /// [...] 238 /// $whatever = COPY $addr 239 bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0); 240 241 bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); 242 bool applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo); 243 244 /// Fold (shift (shift base, x), y) -> (shift base (x+y)) 245 bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); 246 bool applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo); 247 248 /// If we have a shift-by-constant of a bitwise logic op that itself has a 249 /// shift-by-constant operand with identical opcode, we may be able to convert 250 /// that into 2 independent shifts followed by the logic op. 251 bool matchShiftOfShiftedLogic(MachineInstr &MI, 252 ShiftOfShiftedLogic &MatchInfo); 253 bool applyShiftOfShiftedLogic(MachineInstr &MI, 254 ShiftOfShiftedLogic &MatchInfo); 255 256 /// Transform a multiply by a power-of-2 value to a left shift. 257 bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); 258 bool applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal); 259 260 // Transform a G_SHL with an extended source into a narrower shift if 261 // possible. 262 bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData); 263 bool applyCombineShlOfExtend(MachineInstr &MI, 264 const RegisterImmPair &MatchData); 265 266 /// Reduce a shift by a constant to an unmerge and a shift on a half sized 267 /// type. This will not produce a shift smaller than \p TargetShiftSize. 268 bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, 269 unsigned &ShiftVal); 270 bool applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal); 271 bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount); 272 273 /// Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z. 274 bool 275 matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, 276 SmallVectorImpl<Register> &Operands); 277 bool 278 applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, 279 SmallVectorImpl<Register> &Operands); 280 281 /// Transform G_UNMERGE Constant -> Constant1, Constant2, ... 282 bool matchCombineUnmergeConstant(MachineInstr &MI, 283 SmallVectorImpl<APInt> &Csts); 284 bool applyCombineUnmergeConstant(MachineInstr &MI, 285 SmallVectorImpl<APInt> &Csts); 286 287 /// Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z. 288 bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); 289 bool applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI); 290 291 /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0 292 bool matchCombineUnmergeZExtToZExt(MachineInstr &MI); 293 bool applyCombineUnmergeZExtToZExt(MachineInstr &MI); 294 295 /// Transform fp_instr(cst) to constant result of the fp operation. 296 bool matchCombineConstantFoldFpUnary(MachineInstr &MI, 297 Optional<APFloat> &Cst); 298 bool applyCombineConstantFoldFpUnary(MachineInstr &MI, 299 Optional<APFloat> &Cst); 300 301 /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space. 302 bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg); 303 bool applyCombineI2PToP2I(MachineInstr &MI, Register &Reg); 304 305 /// Transform PtrToInt(IntToPtr(x)) to x. 306 bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg); 307 bool applyCombineP2IToI2P(MachineInstr &MI, Register &Reg); 308 309 /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y) 310 /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y) 311 bool matchCombineAddP2IToPtrAdd(MachineInstr &MI, 312 std::pair<Register, bool> &PtrRegAndCommute); 313 bool applyCombineAddP2IToPtrAdd(MachineInstr &MI, 314 std::pair<Register, bool> &PtrRegAndCommute); 315 316 // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2 317 bool matchCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst); 318 bool applyCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst); 319 320 /// Transform anyext(trunc(x)) to x. 321 bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); 322 bool applyCombineAnyExtTrunc(MachineInstr &MI, Register &Reg); 323 324 /// Transform zext(trunc(x)) to x. 325 bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg); 326 327 /// Transform [asz]ext([asz]ext(x)) to [asz]ext x. 328 bool matchCombineExtOfExt(MachineInstr &MI, 329 std::tuple<Register, unsigned> &MatchInfo); 330 bool applyCombineExtOfExt(MachineInstr &MI, 331 std::tuple<Register, unsigned> &MatchInfo); 332 333 /// Transform fneg(fneg(x)) to x. 334 bool matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg); 335 336 /// Match fabs(fabs(x)) to fabs(x). 337 bool matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); 338 bool applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); 339 340 /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x). 341 bool matchCombineTruncOfExt(MachineInstr &MI, 342 std::pair<Register, unsigned> &MatchInfo); 343 bool applyCombineTruncOfExt(MachineInstr &MI, 344 std::pair<Register, unsigned> &MatchInfo); 345 346 /// Transform trunc (shl x, K) to shl (trunc x), 347 /// K => K < VT.getScalarSizeInBits(). 348 bool matchCombineTruncOfShl(MachineInstr &MI, 349 std::pair<Register, Register> &MatchInfo); 350 bool applyCombineTruncOfShl(MachineInstr &MI, 351 std::pair<Register, Register> &MatchInfo); 352 353 /// Transform G_MUL(x, -1) to G_SUB(0, x) 354 bool applyCombineMulByNegativeOne(MachineInstr &MI); 355 356 /// Return true if any explicit use operand on \p MI is defined by a 357 /// G_IMPLICIT_DEF. 358 bool matchAnyExplicitUseIsUndef(MachineInstr &MI); 359 360 /// Return true if all register explicit use operands on \p MI are defined by 361 /// a G_IMPLICIT_DEF. 362 bool matchAllExplicitUsesAreUndef(MachineInstr &MI); 363 364 /// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask. 365 bool matchUndefShuffleVectorMask(MachineInstr &MI); 366 367 /// Return true if a G_STORE instruction \p MI is storing an undef value. 368 bool matchUndefStore(MachineInstr &MI); 369 370 /// Return true if a G_SELECT instruction \p MI has an undef comparison. 371 bool matchUndefSelectCmp(MachineInstr &MI); 372 373 /// Return true if a G_SELECT instruction \p MI has a constant comparison. If 374 /// true, \p OpIdx will store the operand index of the known selected value. 375 bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx); 376 377 /// Replace an instruction with a G_FCONSTANT with value \p C. 378 bool replaceInstWithFConstant(MachineInstr &MI, double C); 379 380 /// Replace an instruction with a G_CONSTANT with value \p C. 381 bool replaceInstWithConstant(MachineInstr &MI, int64_t C); 382 383 /// Replace an instruction with a G_IMPLICIT_DEF. 384 bool replaceInstWithUndef(MachineInstr &MI); 385 386 /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand. 387 bool replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx); 388 389 /// Delete \p MI and replace all of its uses with \p Replacement. 390 bool replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement); 391 392 /// Return true if \p MOP1 and \p MOP2 are register operands are defined by 393 /// equivalent instructions. 394 bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2); 395 396 /// Return true if \p MOP is defined by a G_CONSTANT with a value equal to 397 /// \p C. 398 bool matchConstantOp(const MachineOperand &MOP, int64_t C); 399 400 /// Optimize (cond ? x : x) -> x 401 bool matchSelectSameVal(MachineInstr &MI); 402 403 /// Optimize (x op x) -> x 404 bool matchBinOpSameVal(MachineInstr &MI); 405 406 /// Check if operand \p OpIdx is zero. 407 bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx); 408 409 /// Check if operand \p OpIdx is undef. 410 bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx); 411 412 /// Check if operand \p OpIdx is known to be a power of 2. 413 bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, unsigned OpIdx); 414 415 /// Erase \p MI 416 bool eraseInst(MachineInstr &MI); 417 418 /// Return true if MI is a G_ADD which can be simplified to a G_SUB. 419 bool matchSimplifyAddToSub(MachineInstr &MI, 420 std::tuple<Register, Register> &MatchInfo); 421 bool applySimplifyAddToSub(MachineInstr &MI, 422 std::tuple<Register, Register> &MatchInfo); 423 424 /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) 425 bool 426 matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, 427 InstructionStepsMatchInfo &MatchInfo); 428 429 /// Replace \p MI with a series of instructions described in \p MatchInfo. 430 bool applyBuildInstructionSteps(MachineInstr &MI, 431 InstructionStepsMatchInfo &MatchInfo); 432 433 /// Match ashr (shl x, C), C -> sext_inreg (C) 434 bool matchAshrShlToSextInreg(MachineInstr &MI, 435 std::tuple<Register, int64_t> &MatchInfo); 436 bool applyAshShlToSextInreg(MachineInstr &MI, 437 std::tuple<Register, int64_t> &MatchInfo); 438 /// \return true if \p MI is a G_AND instruction whose operands are x and y 439 /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.) 440 /// 441 /// \param [in] MI - The G_AND instruction. 442 /// \param [out] Replacement - A register the G_AND should be replaced with on 443 /// success. 444 bool matchRedundantAnd(MachineInstr &MI, Register &Replacement); 445 446 /// \return true if \p MI is a G_OR instruction whose operands are x and y 447 /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros 448 /// value.) 449 /// 450 /// \param [in] MI - The G_OR instruction. 451 /// \param [out] Replacement - A register the G_OR should be replaced with on 452 /// success. 453 bool matchRedundantOr(MachineInstr &MI, Register &Replacement); 454 455 /// \return true if \p MI is a G_SEXT_INREG that can be erased. 456 bool matchRedundantSExtInReg(MachineInstr &MI); 457 458 /// Combine inverting a result of a compare into the opposite cond code. 459 bool matchNotCmp(MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate); 460 bool applyNotCmp(MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate); 461 462 /// Fold (xor (and x, y), y) -> (and (not x), y) 463 ///{ 464 bool matchXorOfAndWithSameReg(MachineInstr &MI, 465 std::pair<Register, Register> &MatchInfo); 466 bool applyXorOfAndWithSameReg(MachineInstr &MI, 467 std::pair<Register, Register> &MatchInfo); 468 ///} 469 470 /// Combine G_PTR_ADD with nullptr to G_INTTOPTR 471 bool matchPtrAddZero(MachineInstr &MI); 472 bool applyPtrAddZero(MachineInstr &MI); 473 474 /// Combine G_UREM x, (known power of 2) to an add and bitmasking. 475 bool applySimplifyURemByPow2(MachineInstr &MI); 476 477 bool matchCombineInsertVecElts(MachineInstr &MI, 478 SmallVectorImpl<Register> &MatchInfo); 479 480 bool applyCombineInsertVecElts(MachineInstr &MI, 481 SmallVectorImpl<Register> &MatchInfo); 482 483 /// Match expression trees of the form 484 /// 485 /// \code 486 /// sN *a = ... 487 /// sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ... 488 /// \endcode 489 /// 490 /// And check if the tree can be replaced with a M-bit load + possibly a 491 /// bswap. 492 bool matchLoadOrCombine(MachineInstr &MI, 493 std::function<void(MachineIRBuilder &)> &MatchInfo); 494 495 bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI); 496 bool applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI); 497 498 bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg); 499 void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg); 500 501 bool matchExtractAllEltsFromBuildVector( 502 MachineInstr &MI, 503 SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo); 504 void applyExtractAllEltsFromBuildVector( 505 MachineInstr &MI, 506 SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo); 507 508 /// Use a function which takes in a MachineIRBuilder to perform a combine. 509 bool applyBuildFn(MachineInstr &MI, 510 std::function<void(MachineIRBuilder &)> &MatchInfo); 511 bool matchFunnelShiftToRotate(MachineInstr &MI); 512 void applyFunnelShiftToRotate(MachineInstr &MI); 513 bool matchRotateOutOfRange(MachineInstr &MI); 514 void applyRotateOutOfRange(MachineInstr &MI); 515 516 /// \returns true if a G_ICMP instruction \p MI can be replaced with a true 517 /// or false constant based off of KnownBits information. 518 bool matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo); 519 520 /// Try to transform \p MI by using all of the above 521 /// combine functions. Returns true if changed. 522 bool tryCombine(MachineInstr &MI); 523 524 private: 525 // Memcpy family optimization helpers. 526 bool optimizeMemcpy(MachineInstr &MI, Register Dst, Register Src, 527 unsigned KnownLen, Align DstAlign, Align SrcAlign, 528 bool IsVolatile); 529 bool optimizeMemmove(MachineInstr &MI, Register Dst, Register Src, 530 unsigned KnownLen, Align DstAlign, Align SrcAlign, 531 bool IsVolatile); 532 bool optimizeMemset(MachineInstr &MI, Register Dst, Register Val, 533 unsigned KnownLen, Align DstAlign, bool IsVolatile); 534 535 /// Given a non-indexed load or store instruction \p MI, find an offset that 536 /// can be usefully and legally folded into it as a post-indexing operation. 537 /// 538 /// \returns true if a candidate is found. 539 bool findPostIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base, 540 Register &Offset); 541 542 /// Given a non-indexed load or store instruction \p MI, find an offset that 543 /// can be usefully and legally folded into it as a pre-indexing operation. 544 /// 545 /// \returns true if a candidate is found. 546 bool findPreIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base, 547 Register &Offset); 548 549 /// Helper function for matchLoadOrCombine. Searches for Registers 550 /// which may have been produced by a load instruction + some arithmetic. 551 /// 552 /// \param [in] Root - The search root. 553 /// 554 /// \returns The Registers found during the search. 555 Optional<SmallVector<Register, 8>> 556 findCandidatesForLoadOrCombine(const MachineInstr *Root) const; 557 558 /// Helper function for matchLoadOrCombine. 559 /// 560 /// Checks if every register in \p RegsToVisit is defined by a load 561 /// instruction + some arithmetic. 562 /// 563 /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up 564 /// at to the index of the load. 565 /// \param [in] MemSizeInBits - The number of bits each load should produce. 566 /// 567 /// \returns The lowest-index load found and the lowest index on success. 568 Optional<std::pair<MachineInstr *, int64_t>> findLoadOffsetsForLoadOrCombine( 569 SmallDenseMap<int64_t, int64_t, 8> &MemOffset2Idx, 570 const SmallVector<Register, 8> &RegsToVisit, 571 const unsigned MemSizeInBits); 572 }; 573 } // namespace llvm 574 575 #endif 576