10b57cec5SDimitry Andric //===-- X86InstrInfo.h - X86 Instruction Information ------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the X86 implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_X86_X86INSTRINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_X86_X86INSTRINFO_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "MCTargetDesc/X86BaseInfo.h" 170b57cec5SDimitry Andric #include "X86InstrFMA3Info.h" 180b57cec5SDimitry Andric #include "X86RegisterInfo.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 210b57cec5SDimitry Andric #include <vector> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER 240b57cec5SDimitry Andric #include "X86GenInstrInfo.inc" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace llvm { 270b57cec5SDimitry Andric class X86Subtarget; 280b57cec5SDimitry Andric 29*0fca6ea1SDimitry Andric // X86 MachineCombiner patterns 30*0fca6ea1SDimitry Andric enum X86MachineCombinerPattern : unsigned { 31*0fca6ea1SDimitry Andric // X86 VNNI 32*0fca6ea1SDimitry Andric DPWSSD = MachineCombinerPattern::TARGET_PATTERN_START, 33*0fca6ea1SDimitry Andric }; 34*0fca6ea1SDimitry Andric 350b57cec5SDimitry Andric namespace X86 { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric enum AsmComments { 381db9f3b2SDimitry Andric // For instr that was compressed from EVEX to LEGACY. 391db9f3b2SDimitry Andric AC_EVEX_2_LEGACY = MachineInstr::TAsmComments, 400b57cec5SDimitry Andric // For instr that was compressed from EVEX to VEX. 417a6dacacSDimitry Andric AC_EVEX_2_VEX = AC_EVEX_2_LEGACY << 1, 427a6dacacSDimitry Andric // For instr that was compressed from EVEX to EVEX. 437a6dacacSDimitry Andric AC_EVEX_2_EVEX = AC_EVEX_2_VEX << 1 440b57cec5SDimitry Andric }; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// Return a pair of condition code for the given predicate and whether 470b57cec5SDimitry Andric /// the instruction operands should be swaped to match the condition code. 480b57cec5SDimitry Andric std::pair<CondCode, bool> getX86ConditionCode(CmpInst::Predicate Predicate); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric /// Return a cmov opcode for the given register size in bytes, and operand type. 51*0fca6ea1SDimitry Andric unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand = false, 52*0fca6ea1SDimitry Andric bool HasNDD = false); 530b57cec5SDimitry Andric 5481ad6265SDimitry Andric /// Return the source operand # for condition code by \p MCID. If the 5581ad6265SDimitry Andric /// instruction doesn't have a condition code, return -1. 5681ad6265SDimitry Andric int getCondSrcNoFromDesc(const MCInstrDesc &MCID); 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric /// Return the condition code of the instruction. If the instruction doesn't 5981ad6265SDimitry Andric /// have a condition code, return X86::COND_INVALID. 6081ad6265SDimitry Andric CondCode getCondFromMI(const MachineInstr &MI); 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric // Turn JCC instruction into condition code. 630b57cec5SDimitry Andric CondCode getCondFromBranch(const MachineInstr &MI); 640b57cec5SDimitry Andric 6581ad6265SDimitry Andric // Turn SETCC instruction into condition code. 660b57cec5SDimitry Andric CondCode getCondFromSETCC(const MachineInstr &MI); 670b57cec5SDimitry Andric 6881ad6265SDimitry Andric // Turn CMOV instruction into condition code. 690b57cec5SDimitry Andric CondCode getCondFromCMov(const MachineInstr &MI); 700b57cec5SDimitry Andric 71*0fca6ea1SDimitry Andric // Turn CFCMOV instruction into condition code. 72*0fca6ea1SDimitry Andric CondCode getCondFromCFCMov(const MachineInstr &MI); 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric // Turn CCMP instruction into condition code. 75*0fca6ea1SDimitry Andric CondCode getCondFromCCMP(const MachineInstr &MI); 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric // Turn condition code into condition flags for CCMP/CTEST. 78*0fca6ea1SDimitry Andric int getCCMPCondFlagsFromCondCode(CondCode CC); 79*0fca6ea1SDimitry Andric 80*0fca6ea1SDimitry Andric // Get the opcode of corresponding NF variant. 81*0fca6ea1SDimitry Andric unsigned getNFVariant(unsigned Opc); 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric // Get the opcode of corresponding NonND variant. 84*0fca6ea1SDimitry Andric unsigned getNonNDVariant(unsigned Opc); 85*0fca6ea1SDimitry Andric 860b57cec5SDimitry Andric /// GetOppositeBranchCondition - Return the inverse of the specified cond, 870b57cec5SDimitry Andric /// e.g. turning COND_E to COND_NE. 880b57cec5SDimitry Andric CondCode GetOppositeBranchCondition(CondCode CC); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// Get the VPCMP immediate for the given condition. 910b57cec5SDimitry Andric unsigned getVPCMPImmForCond(ISD::CondCode CC); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric /// Get the VPCMP immediate if the opcodes are swapped. 940b57cec5SDimitry Andric unsigned getSwappedVPCMPImm(unsigned Imm); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// Get the VPCOM immediate if the opcodes are swapped. 970b57cec5SDimitry Andric unsigned getSwappedVPCOMImm(unsigned Imm); 980b57cec5SDimitry Andric 998bcb0991SDimitry Andric /// Get the VCMP immediate if the opcodes are swapped. 1008bcb0991SDimitry Andric unsigned getSwappedVCMPImm(unsigned Imm); 1018bcb0991SDimitry Andric 102*0fca6ea1SDimitry Andric /// Get the width of the vector register operand. 103*0fca6ea1SDimitry Andric unsigned getVectorRegisterWidth(const MCOperandInfo &Info); 104*0fca6ea1SDimitry Andric 105349cc55cSDimitry Andric /// Check if the instruction is X87 instruction. 106349cc55cSDimitry Andric bool isX87Instruction(MachineInstr &MI); 1077a6dacacSDimitry Andric 1087a6dacacSDimitry Andric /// Return the index of the instruction's first address operand, if it has a 1097a6dacacSDimitry Andric /// memory reference, or -1 if it has none. Unlike X86II::getMemoryOperandNo(), 1107a6dacacSDimitry Andric /// this also works for both pseudo instructions (e.g., TCRETURNmi) as well as 1117a6dacacSDimitry Andric /// real instructions (e.g., JMP64m). 1127a6dacacSDimitry Andric int getFirstAddrOperandIdx(const MachineInstr &MI); 1137a6dacacSDimitry Andric 1147a6dacacSDimitry Andric /// Find any constant pool entry associated with a specific instruction operand. 1157a6dacacSDimitry Andric const Constant *getConstantFromPool(const MachineInstr &MI, unsigned OpNo); 1167a6dacacSDimitry Andric 1170b57cec5SDimitry Andric } // namespace X86 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// isGlobalStubReference - Return true if the specified TargetFlag operand is 1200b57cec5SDimitry Andric /// a reference to a stub for a global, not the global itself. 1210b57cec5SDimitry Andric inline static bool isGlobalStubReference(unsigned char TargetFlag) { 1220b57cec5SDimitry Andric switch (TargetFlag) { 1230b57cec5SDimitry Andric case X86II::MO_DLLIMPORT: // dllimport stub. 1240b57cec5SDimitry Andric case X86II::MO_GOTPCREL: // rip-relative GOT reference. 125349cc55cSDimitry Andric case X86II::MO_GOTPCREL_NORELAX: // rip-relative GOT reference. 1260b57cec5SDimitry Andric case X86II::MO_GOT: // normal GOT reference. 1270b57cec5SDimitry Andric case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref. 1280b57cec5SDimitry Andric case X86II::MO_DARWIN_NONLAZY: // Normal $non_lazy_ptr ref. 1290b57cec5SDimitry Andric case X86II::MO_COFFSTUB: // COFF .refptr stub. 1300b57cec5SDimitry Andric return true; 1310b57cec5SDimitry Andric default: 1320b57cec5SDimitry Andric return false; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// isGlobalRelativeToPICBase - Return true if the specified global value 1370b57cec5SDimitry Andric /// reference is relative to a 32-bit PIC base (X86ISD::GlobalBaseReg). If this 1380b57cec5SDimitry Andric /// is true, the addressing mode has the PIC base register added in (e.g. EBX). 1390b57cec5SDimitry Andric inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) { 1400b57cec5SDimitry Andric switch (TargetFlag) { 1410b57cec5SDimitry Andric case X86II::MO_GOTOFF: // isPICStyleGOT: local global. 1420b57cec5SDimitry Andric case X86II::MO_GOT: // isPICStyleGOT: other global. 1430b57cec5SDimitry Andric case X86II::MO_PIC_BASE_OFFSET: // Darwin local global. 1440b57cec5SDimitry Andric case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global. 1450b57cec5SDimitry Andric case X86II::MO_TLVP: // ??? Pretty sure.. 1460b57cec5SDimitry Andric return true; 1470b57cec5SDimitry Andric default: 1480b57cec5SDimitry Andric return false; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric inline static bool isScale(const MachineOperand &MO) { 1530b57cec5SDimitry Andric return MO.isImm() && (MO.getImm() == 1 || MO.getImm() == 2 || 1540b57cec5SDimitry Andric MO.getImm() == 4 || MO.getImm() == 8); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric inline static bool isLeaMem(const MachineInstr &MI, unsigned Op) { 1580b57cec5SDimitry Andric if (MI.getOperand(Op).isFI()) 1590b57cec5SDimitry Andric return true; 1600b57cec5SDimitry Andric return Op + X86::AddrSegmentReg <= MI.getNumOperands() && 1610b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrBaseReg).isReg() && 1620b57cec5SDimitry Andric isScale(MI.getOperand(Op + X86::AddrScaleAmt)) && 1630b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrIndexReg).isReg() && 1640b57cec5SDimitry Andric (MI.getOperand(Op + X86::AddrDisp).isImm() || 1650b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrDisp).isGlobal() || 1660b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrDisp).isCPI() || 1670b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrDisp).isJTI()); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric inline static bool isMem(const MachineInstr &MI, unsigned Op) { 1710b57cec5SDimitry Andric if (MI.getOperand(Op).isFI()) 1720b57cec5SDimitry Andric return true; 1730b57cec5SDimitry Andric return Op + X86::AddrNumOperands <= MI.getNumOperands() && 1740b57cec5SDimitry Andric MI.getOperand(Op + X86::AddrSegmentReg).isReg() && isLeaMem(MI, Op); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric class X86InstrInfo final : public X86GenInstrInfo { 1780b57cec5SDimitry Andric X86Subtarget &Subtarget; 1790b57cec5SDimitry Andric const X86RegisterInfo RI; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric virtual void anchor(); 1820b57cec5SDimitry Andric 183*0fca6ea1SDimitry Andric bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 1840b57cec5SDimitry Andric MachineBasicBlock *&FBB, 1850b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 1860b57cec5SDimitry Andric SmallVectorImpl<MachineInstr *> &CondBranches, 1870b57cec5SDimitry Andric bool AllowModify) const; 1880b57cec5SDimitry Andric 189*0fca6ea1SDimitry Andric bool foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI, Register Reg, 190*0fca6ea1SDimitry Andric int64_t ImmVal, MachineRegisterInfo *MRI, 191*0fca6ea1SDimitry Andric bool MakeChange) const; 192*0fca6ea1SDimitry Andric 1930b57cec5SDimitry Andric public: 1940b57cec5SDimitry Andric explicit X86InstrInfo(X86Subtarget &STI); 1950b57cec5SDimitry Andric 1965f757f3fSDimitry Andric /// Given a machine instruction descriptor, returns the register 1975f757f3fSDimitry Andric /// class constraint for OpNum, or NULL. Returned register class 1985f757f3fSDimitry Andric /// may be different from the definition in the TD file, e.g. 1995f757f3fSDimitry Andric /// GR*RegClass (definition in TD file) 2005f757f3fSDimitry Andric /// -> 2015f757f3fSDimitry Andric /// GR*_NOREX2RegClass (Returned register class) 2025f757f3fSDimitry Andric const TargetRegisterClass * 2035f757f3fSDimitry Andric getRegClass(const MCInstrDesc &MCID, unsigned OpNum, 2045f757f3fSDimitry Andric const TargetRegisterInfo *TRI, 2055f757f3fSDimitry Andric const MachineFunction &MF) const override; 2065f757f3fSDimitry Andric 2070b57cec5SDimitry Andric /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As 2080b57cec5SDimitry Andric /// such, whenever a client has an instance of instruction info, it should 2090b57cec5SDimitry Andric /// always be able to get register info as well (through this method). 2100b57cec5SDimitry Andric /// 2110b57cec5SDimitry Andric const X86RegisterInfo &getRegisterInfo() const { return RI; } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric /// Returns the stack pointer adjustment that happens inside the frame 2140b57cec5SDimitry Andric /// setup..destroy sequence (e.g. by pushes, or inside the callee). 2150b57cec5SDimitry Andric int64_t getFrameAdjustment(const MachineInstr &I) const { 2160b57cec5SDimitry Andric assert(isFrameInstr(I)); 2170b57cec5SDimitry Andric if (isFrameSetup(I)) 2180b57cec5SDimitry Andric return I.getOperand(2).getImm(); 2190b57cec5SDimitry Andric return I.getOperand(1).getImm(); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric /// Sets the stack pointer adjustment made inside the frame made up by this 2230b57cec5SDimitry Andric /// instruction. 2240b57cec5SDimitry Andric void setFrameAdjustment(MachineInstr &I, int64_t V) const { 2250b57cec5SDimitry Andric assert(isFrameInstr(I)); 2260b57cec5SDimitry Andric if (isFrameSetup(I)) 2270b57cec5SDimitry Andric I.getOperand(2).setImm(V); 2280b57cec5SDimitry Andric else 2290b57cec5SDimitry Andric I.getOperand(1).setImm(V); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric /// getSPAdjust - This returns the stack pointer adjustment made by 2330b57cec5SDimitry Andric /// this instruction. For x86, we need to handle more complex call 2340b57cec5SDimitry Andric /// sequences involving PUSHes. 2350b57cec5SDimitry Andric int getSPAdjust(const MachineInstr &MI) const override; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" 2380b57cec5SDimitry Andric /// extension instruction. That is, it's like a copy where it's legal for the 2390b57cec5SDimitry Andric /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns 2400b57cec5SDimitry Andric /// true, then it's expected the pre-extension value is available as a subreg 2410b57cec5SDimitry Andric /// of the result register. This also returns the sub-register index in 2420b57cec5SDimitry Andric /// SubIdx. 2435ffd83dbSDimitry Andric bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, 2445ffd83dbSDimitry Andric Register &DstReg, unsigned &SubIdx) const override; 2455ffd83dbSDimitry Andric 2465ffd83dbSDimitry Andric /// Returns true if the instruction has no behavior (specified or otherwise) 2475ffd83dbSDimitry Andric /// that is based on the value of any of its register operands 2485ffd83dbSDimitry Andric /// 2495ffd83dbSDimitry Andric /// Instructions are considered data invariant even if they set EFLAGS. 2505ffd83dbSDimitry Andric /// 2515ffd83dbSDimitry Andric /// A classical example of something that is inherently not data invariant is 2525ffd83dbSDimitry Andric /// an indirect jump -- the destination is loaded into icache based on the 2535ffd83dbSDimitry Andric /// bits set in the jump destination register. 2545ffd83dbSDimitry Andric /// 2555ffd83dbSDimitry Andric /// FIXME: This should become part of our instruction tables. 2565ffd83dbSDimitry Andric static bool isDataInvariant(MachineInstr &MI); 2575ffd83dbSDimitry Andric 2585ffd83dbSDimitry Andric /// Returns true if the instruction has no behavior (specified or otherwise) 2595ffd83dbSDimitry Andric /// that is based on the value loaded from memory or the value of any 2605ffd83dbSDimitry Andric /// non-address register operands. 2615ffd83dbSDimitry Andric /// 2625ffd83dbSDimitry Andric /// For example, if the latency of the instruction is dependent on the 2635ffd83dbSDimitry Andric /// particular bits set in any of the registers *or* any of the bits loaded 2645ffd83dbSDimitry Andric /// from memory. 2655ffd83dbSDimitry Andric /// 2665ffd83dbSDimitry Andric /// Instructions are considered data invariant even if they set EFLAGS. 2675ffd83dbSDimitry Andric /// 2685ffd83dbSDimitry Andric /// A classical example of something that is inherently not data invariant is 2695ffd83dbSDimitry Andric /// an indirect jump -- the destination is loaded into icache based on the 2705ffd83dbSDimitry Andric /// bits set in the jump destination register. 2715ffd83dbSDimitry Andric /// 2725ffd83dbSDimitry Andric /// FIXME: This should become part of our instruction tables. 2735ffd83dbSDimitry Andric static bool isDataInvariantLoad(MachineInstr &MI); 2740b57cec5SDimitry Andric 275*0fca6ea1SDimitry Andric Register isLoadFromStackSlot(const MachineInstr &MI, 2760b57cec5SDimitry Andric int &FrameIndex) const override; 277*0fca6ea1SDimitry Andric Register isLoadFromStackSlot(const MachineInstr &MI, 2780b57cec5SDimitry Andric int &FrameIndex, 2790b57cec5SDimitry Andric unsigned &MemBytes) const override; 2800b57cec5SDimitry Andric /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination 2810b57cec5SDimitry Andric /// stack locations as well. This uses a heuristic so it isn't 2820b57cec5SDimitry Andric /// reliable for correctness. 283*0fca6ea1SDimitry Andric Register isLoadFromStackSlotPostFE(const MachineInstr &MI, 2840b57cec5SDimitry Andric int &FrameIndex) const override; 2850b57cec5SDimitry Andric 286*0fca6ea1SDimitry Andric Register isStoreToStackSlot(const MachineInstr &MI, 2870b57cec5SDimitry Andric int &FrameIndex) const override; 288*0fca6ea1SDimitry Andric Register isStoreToStackSlot(const MachineInstr &MI, 2890b57cec5SDimitry Andric int &FrameIndex, 2900b57cec5SDimitry Andric unsigned &MemBytes) const override; 2910b57cec5SDimitry Andric /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination 2920b57cec5SDimitry Andric /// stack locations as well. This uses a heuristic so it isn't 2930b57cec5SDimitry Andric /// reliable for correctness. 294*0fca6ea1SDimitry Andric Register isStoreToStackSlotPostFE(const MachineInstr &MI, 2950b57cec5SDimitry Andric int &FrameIndex) const override; 2960b57cec5SDimitry Andric 297fcaf7f86SDimitry Andric bool isReallyTriviallyReMaterializable(const MachineInstr &MI) const override; 2980b57cec5SDimitry Andric void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 2995ffd83dbSDimitry Andric Register DestReg, unsigned SubIdx, 3000b57cec5SDimitry Andric const MachineInstr &Orig, 3010b57cec5SDimitry Andric const TargetRegisterInfo &TRI) const override; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric /// Given an operand within a MachineInstr, insert preceding code to put it 3040b57cec5SDimitry Andric /// into the right format for a particular kind of LEA instruction. This may 3050b57cec5SDimitry Andric /// involve using an appropriate super-register instead (with an implicit use 3060b57cec5SDimitry Andric /// of the original) or creating a new virtual register and inserting COPY 3070b57cec5SDimitry Andric /// instructions to get the data into the right class. 3080b57cec5SDimitry Andric /// 3090b57cec5SDimitry Andric /// Reference parameters are set to indicate how caller should add this 3100b57cec5SDimitry Andric /// operand to the LEA instruction. 3110b57cec5SDimitry Andric bool classifyLEAReg(MachineInstr &MI, const MachineOperand &Src, 3128bcb0991SDimitry Andric unsigned LEAOpcode, bool AllowSP, Register &NewSrc, 3130b57cec5SDimitry Andric bool &isKill, MachineOperand &ImplicitOp, 314349cc55cSDimitry Andric LiveVariables *LV, LiveIntervals *LIS) const; 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric /// convertToThreeAddress - This method must be implemented by targets that 3170b57cec5SDimitry Andric /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target 3180b57cec5SDimitry Andric /// may be able to convert a two-address instruction into a true 3190b57cec5SDimitry Andric /// three-address instruction on demand. This allows the X86 target (for 3200b57cec5SDimitry Andric /// example) to convert ADD and SHL instructions into LEA instructions if they 3210b57cec5SDimitry Andric /// would require register copies due to two-addressness. 3220b57cec5SDimitry Andric /// 3230b57cec5SDimitry Andric /// This method returns a null pointer if the transformation cannot be 3240b57cec5SDimitry Andric /// performed, otherwise it returns the new instruction. 3250b57cec5SDimitry Andric /// 326349cc55cSDimitry Andric MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, 327349cc55cSDimitry Andric LiveIntervals *LIS) const override; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric /// Returns true iff the routine could find two commutable operands in the 3300b57cec5SDimitry Andric /// given machine instruction. 3310b57cec5SDimitry Andric /// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. Their 3320b57cec5SDimitry Andric /// input values can be re-defined in this method only if the input values 3330b57cec5SDimitry Andric /// are not pre-defined, which is designated by the special value 3340b57cec5SDimitry Andric /// 'CommuteAnyOperandIndex' assigned to it. 3350b57cec5SDimitry Andric /// If both of indices are pre-defined and refer to some operands, then the 3360b57cec5SDimitry Andric /// method simply returns true if the corresponding operands are commutable 3370b57cec5SDimitry Andric /// and returns false otherwise. 3380b57cec5SDimitry Andric /// 3390b57cec5SDimitry Andric /// For example, calling this method this way: 3400b57cec5SDimitry Andric /// unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex; 3410b57cec5SDimitry Andric /// findCommutedOpIndices(MI, Op1, Op2); 3420b57cec5SDimitry Andric /// can be interpreted as a query asking to find an operand that would be 3430b57cec5SDimitry Andric /// commutable with the operand#1. 3448bcb0991SDimitry Andric bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 3450b57cec5SDimitry Andric unsigned &SrcOpIdx2) const override; 3460b57cec5SDimitry Andric 347fe6060f1SDimitry Andric /// Returns true if we have preference on the operands order in MI, the 348fe6060f1SDimitry Andric /// commute decision is returned in Commute. 349fe6060f1SDimitry Andric bool hasCommutePreference(MachineInstr &MI, bool &Commute) const override; 350fe6060f1SDimitry Andric 3510b57cec5SDimitry Andric /// Returns an adjusted FMA opcode that must be used in FMA instruction that 3520b57cec5SDimitry Andric /// performs the same computations as the given \p MI but which has the 3530b57cec5SDimitry Andric /// operands \p SrcOpIdx1 and \p SrcOpIdx2 commuted. 3540b57cec5SDimitry Andric /// It may return 0 if it is unsafe to commute the operands. 3550b57cec5SDimitry Andric /// Note that a machine instruction (instead of its opcode) is passed as the 3560b57cec5SDimitry Andric /// first parameter to make it possible to analyze the instruction's uses and 3570b57cec5SDimitry Andric /// commute the first operand of FMA even when it seems unsafe when you look 3580b57cec5SDimitry Andric /// at the opcode. For example, it is Ok to commute the first operand of 3590b57cec5SDimitry Andric /// VFMADD*SD_Int, if ONLY the lowest 64-bit element of the result is used. 3600b57cec5SDimitry Andric /// 3610b57cec5SDimitry Andric /// The returned FMA opcode may differ from the opcode in the given \p MI. 3620b57cec5SDimitry Andric /// For example, commuting the operands #1 and #3 in the following FMA 3630b57cec5SDimitry Andric /// FMA213 #1, #2, #3 3640b57cec5SDimitry Andric /// results into instruction with adjusted opcode: 3650b57cec5SDimitry Andric /// FMA231 #3, #2, #1 3660b57cec5SDimitry Andric unsigned 3670b57cec5SDimitry Andric getFMA3OpcodeToCommuteOperands(const MachineInstr &MI, unsigned SrcOpIdx1, 3680b57cec5SDimitry Andric unsigned SrcOpIdx2, 3690b57cec5SDimitry Andric const X86InstrFMA3Group &FMA3Group) const; 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric // Branch analysis. 3720b57cec5SDimitry Andric bool isUnconditionalTailCall(const MachineInstr &MI) const override; 3730b57cec5SDimitry Andric bool canMakeTailCallConditional(SmallVectorImpl<MachineOperand> &Cond, 3740b57cec5SDimitry Andric const MachineInstr &TailCall) const override; 3750b57cec5SDimitry Andric void replaceBranchWithTailCall(MachineBasicBlock &MBB, 3760b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 3770b57cec5SDimitry Andric const MachineInstr &TailCall) const override; 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 3800b57cec5SDimitry Andric MachineBasicBlock *&FBB, 3810b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 3820b57cec5SDimitry Andric bool AllowModify) const override; 3830b57cec5SDimitry Andric 38406c3fb27SDimitry Andric int getJumpTableIndex(const MachineInstr &MI) const override; 38506c3fb27SDimitry Andric 386bdd1243dSDimitry Andric std::optional<ExtAddrMode> 387e8d8bef9SDimitry Andric getAddrModeFromMemoryOp(const MachineInstr &MemI, 388e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI) const override; 389e8d8bef9SDimitry Andric 390e8d8bef9SDimitry Andric bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, 391e8d8bef9SDimitry Andric int64_t &ImmVal) const override; 392e8d8bef9SDimitry Andric 393e8d8bef9SDimitry Andric bool preservesZeroValueInReg(const MachineInstr *MI, 394e8d8bef9SDimitry Andric const Register NullValueReg, 395e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI) const override; 396e8d8bef9SDimitry Andric 3975ffd83dbSDimitry Andric bool getMemOperandsWithOffsetWidth( 3985ffd83dbSDimitry Andric const MachineInstr &LdSt, 3995ffd83dbSDimitry Andric SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset, 400*0fca6ea1SDimitry Andric bool &OffsetIsScalable, LocationSize &Width, 4010b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 4020b57cec5SDimitry Andric bool analyzeBranchPredicate(MachineBasicBlock &MBB, 4030b57cec5SDimitry Andric TargetInstrInfo::MachineBranchPredicate &MBP, 4040b57cec5SDimitry Andric bool AllowModify = false) const override; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric unsigned removeBranch(MachineBasicBlock &MBB, 4070b57cec5SDimitry Andric int *BytesRemoved = nullptr) const override; 4080b57cec5SDimitry Andric unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 4090b57cec5SDimitry Andric MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 4100b57cec5SDimitry Andric const DebugLoc &DL, 4110b57cec5SDimitry Andric int *BytesAdded = nullptr) const override; 4120b57cec5SDimitry Andric bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond, 4135ffd83dbSDimitry Andric Register, Register, Register, int &, int &, 4145ffd83dbSDimitry Andric int &) const override; 4150b57cec5SDimitry Andric void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 4165ffd83dbSDimitry Andric const DebugLoc &DL, Register DstReg, 4175ffd83dbSDimitry Andric ArrayRef<MachineOperand> Cond, Register TrueReg, 4185ffd83dbSDimitry Andric Register FalseReg) const override; 4190b57cec5SDimitry Andric void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 420480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, 4210b57cec5SDimitry Andric bool KillSrc) const override; 4220b57cec5SDimitry Andric void storeRegToStackSlot(MachineBasicBlock &MBB, 4235ffd83dbSDimitry Andric MachineBasicBlock::iterator MI, Register SrcReg, 4240b57cec5SDimitry Andric bool isKill, int FrameIndex, 4250b57cec5SDimitry Andric const TargetRegisterClass *RC, 426bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 427bdd1243dSDimitry Andric Register VReg) const override; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric void loadRegFromStackSlot(MachineBasicBlock &MBB, 4305ffd83dbSDimitry Andric MachineBasicBlock::iterator MI, Register DestReg, 4310b57cec5SDimitry Andric int FrameIndex, const TargetRegisterClass *RC, 432bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 433bdd1243dSDimitry Andric Register VReg) const override; 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric void loadStoreTileReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 436bdd1243dSDimitry Andric unsigned Opc, Register Reg, int FrameIdx, 437bdd1243dSDimitry Andric bool isKill = false) const; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric bool expandPostRAPseudo(MachineInstr &MI) const override; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric /// Check whether the target can fold a load that feeds a subreg operand 4420b57cec5SDimitry Andric /// (or a subreg operand that feeds a store). 4430b57cec5SDimitry Andric bool isSubregFoldable() const override { return true; } 4440b57cec5SDimitry Andric 445*0fca6ea1SDimitry Andric /// Fold a load or store of the specified stack slot into the specified 446*0fca6ea1SDimitry Andric /// machine instruction for the specified operand(s). If folding happens, it 447*0fca6ea1SDimitry Andric /// is likely that the referenced instruction has been changed. 448*0fca6ea1SDimitry Andric /// 449*0fca6ea1SDimitry Andric /// \returns true on success. 4500b57cec5SDimitry Andric MachineInstr * 4510b57cec5SDimitry Andric foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 4520b57cec5SDimitry Andric ArrayRef<unsigned> Ops, 4530b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPt, int FrameIndex, 4540b57cec5SDimitry Andric LiveIntervals *LIS = nullptr, 4550b57cec5SDimitry Andric VirtRegMap *VRM = nullptr) const override; 4560b57cec5SDimitry Andric 457*0fca6ea1SDimitry Andric /// Same as the previous version except it allows folding of any load and 458*0fca6ea1SDimitry Andric /// store from / to any address, not just from a specific stack slot. 4590b57cec5SDimitry Andric MachineInstr *foldMemoryOperandImpl( 4600b57cec5SDimitry Andric MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, 4610b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, 4620b57cec5SDimitry Andric LiveIntervals *LIS = nullptr) const override; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric bool 4650b57cec5SDimitry Andric unfoldMemoryOperand(MachineFunction &MF, MachineInstr &MI, unsigned Reg, 4660b57cec5SDimitry Andric bool UnfoldLoad, bool UnfoldStore, 4670b57cec5SDimitry Andric SmallVectorImpl<MachineInstr *> &NewMIs) const override; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, 4700b57cec5SDimitry Andric SmallVectorImpl<SDNode *> &NewNodes) const override; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric unsigned 4730b57cec5SDimitry Andric getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore, 4740b57cec5SDimitry Andric unsigned *LoadRegIndex = nullptr) const override; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, 4770b57cec5SDimitry Andric int64_t &Offset2) const override; 4780b57cec5SDimitry Andric 479*0fca6ea1SDimitry Andric /// Overrides the isSchedulingBoundary from Codegen/TargetInstrInfo.cpp to 480*0fca6ea1SDimitry Andric /// make it capable of identifying ENDBR intructions and prevent it from being 481*0fca6ea1SDimitry Andric /// re-scheduled. 482e8d8bef9SDimitry Andric bool isSchedulingBoundary(const MachineInstr &MI, 483e8d8bef9SDimitry Andric const MachineBasicBlock *MBB, 484e8d8bef9SDimitry Andric const MachineFunction &MF) const override; 485e8d8bef9SDimitry Andric 486*0fca6ea1SDimitry Andric /// This is a used by the pre-regalloc scheduler to determine (in conjunction 487*0fca6ea1SDimitry Andric /// with areLoadsFromSameBasePtr) if two loads should be scheduled togther. On 488*0fca6ea1SDimitry Andric /// some targets if two loads are loading from addresses in the same cache 489*0fca6ea1SDimitry Andric /// line, it's better if they are scheduled together. This function takes two 490*0fca6ea1SDimitry Andric /// integers that represent the load offsets from the common base address. It 491*0fca6ea1SDimitry Andric /// returns true if it decides it's desirable to schedule the two loads 492*0fca6ea1SDimitry Andric /// together. "NumLoads" is the number of loads that have already been 493*0fca6ea1SDimitry Andric /// scheduled after Load1. 4940b57cec5SDimitry Andric bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, 4950b57cec5SDimitry Andric int64_t Offset2, 4960b57cec5SDimitry Andric unsigned NumLoads) const override; 4970b57cec5SDimitry Andric 4985f757f3fSDimitry Andric void insertNoop(MachineBasicBlock &MBB, 4995f757f3fSDimitry Andric MachineBasicBlock::iterator MI) const override; 5005f757f3fSDimitry Andric 501fe6060f1SDimitry Andric MCInst getNop() const override; 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric bool 5040b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const override; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric /// True if MI has a condition code def, e.g. EFLAGS, that is 5090b57cec5SDimitry Andric /// not marked dead. 5100b57cec5SDimitry Andric bool hasLiveCondCodeDef(MachineInstr &MI) const; 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric /// getGlobalBaseReg - Return a virtual register initialized with the 5130b57cec5SDimitry Andric /// the global base register value. Output instructions required to 5140b57cec5SDimitry Andric /// initialize the register in the function entry block, if necessary. 5150b57cec5SDimitry Andric /// 5160b57cec5SDimitry Andric unsigned getGlobalBaseReg(MachineFunction *MF) const; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric std::pair<uint16_t, uint16_t> 5190b57cec5SDimitry Andric getExecutionDomain(const MachineInstr &MI) const override; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric uint16_t getExecutionDomainCustom(const MachineInstr &MI) const; 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric bool setExecutionDomainCustom(MachineInstr &MI, unsigned Domain) const; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric unsigned 5280b57cec5SDimitry Andric getPartialRegUpdateClearance(const MachineInstr &MI, unsigned OpNum, 5290b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 530e8d8bef9SDimitry Andric unsigned getUndefRegClearance(const MachineInstr &MI, unsigned OpNum, 5310b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 5320b57cec5SDimitry Andric void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, 5330b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 5360b57cec5SDimitry Andric unsigned OpNum, 5370b57cec5SDimitry Andric ArrayRef<MachineOperand> MOs, 5380b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPt, 5395ffd83dbSDimitry Andric unsigned Size, Align Alignment, 5400b57cec5SDimitry Andric bool AllowCommute) const; 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric bool isHighLatencyDef(int opc) const override; 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric bool hasHighOperandLatency(const TargetSchedModel &SchedModel, 5450b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 5460b57cec5SDimitry Andric const MachineInstr &DefMI, unsigned DefIdx, 5470b57cec5SDimitry Andric const MachineInstr &UseMI, 5480b57cec5SDimitry Andric unsigned UseIdx) const override; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric bool useMachineCombiner() const override { return true; } 5510b57cec5SDimitry Andric 552bdd1243dSDimitry Andric bool isAssociativeAndCommutative(const MachineInstr &Inst, 553bdd1243dSDimitry Andric bool Invert) const override; 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric bool hasReassociableOperands(const MachineInstr &Inst, 5560b57cec5SDimitry Andric const MachineBasicBlock *MBB) const override; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2, 5590b57cec5SDimitry Andric MachineInstr &NewMI1, 5600b57cec5SDimitry Andric MachineInstr &NewMI2) const override; 5610b57cec5SDimitry Andric 5625ffd83dbSDimitry Andric bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, 563349cc55cSDimitry Andric Register &SrcReg2, int64_t &CmpMask, 564349cc55cSDimitry Andric int64_t &CmpValue) const override; 5650b57cec5SDimitry Andric 566*0fca6ea1SDimitry Andric /// Check if there exists an earlier instruction that operates on the same 567*0fca6ea1SDimitry Andric /// source operands and sets eflags in the same way as CMP and remove CMP if 568*0fca6ea1SDimitry Andric /// possible. 5695ffd83dbSDimitry Andric bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, 570349cc55cSDimitry Andric Register SrcReg2, int64_t CmpMask, int64_t CmpValue, 5710b57cec5SDimitry Andric const MachineRegisterInfo *MRI) const override; 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric MachineInstr *optimizeLoadInstr(MachineInstr &MI, 5740b57cec5SDimitry Andric const MachineRegisterInfo *MRI, 575e8d8bef9SDimitry Andric Register &FoldAsLoadDefReg, 5760b57cec5SDimitry Andric MachineInstr *&DefMI) const override; 5770b57cec5SDimitry Andric 578*0fca6ea1SDimitry Andric bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, 5795f757f3fSDimitry Andric MachineRegisterInfo *MRI) const override; 5805f757f3fSDimitry Andric 5810b57cec5SDimitry Andric std::pair<unsigned, unsigned> 5820b57cec5SDimitry Andric decomposeMachineOperandsTargetFlags(unsigned TF) const override; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 5850b57cec5SDimitry Andric getSerializableDirectMachineOperandTargetFlags() const override; 5860b57cec5SDimitry Andric 58706c3fb27SDimitry Andric std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo( 5880b57cec5SDimitry Andric std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override; 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric bool isFunctionSafeToOutlineFrom(MachineFunction &MF, 5910b57cec5SDimitry Andric bool OutlineFromLinkOnceODRs) const override; 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric outliner::InstrType 59406c3fb27SDimitry Andric getOutliningTypeImpl(MachineBasicBlock::iterator &MIT, unsigned Flags) const override; 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, 5970b57cec5SDimitry Andric const outliner::OutlinedFunction &OF) const override; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric MachineBasicBlock::iterator 6000b57cec5SDimitry Andric insertOutlinedCall(Module &M, MachineBasicBlock &MBB, 6010b57cec5SDimitry Andric MachineBasicBlock::iterator &It, MachineFunction &MF, 60281ad6265SDimitry Andric outliner::Candidate &C) const override; 6030b57cec5SDimitry Andric 6045f757f3fSDimitry Andric void buildClearRegister(Register Reg, MachineBasicBlock &MBB, 6055f757f3fSDimitry Andric MachineBasicBlock::iterator Iter, DebugLoc &DL, 6065f757f3fSDimitry Andric bool AllowSideEffects = true) const override; 6075f757f3fSDimitry Andric 60881ad6265SDimitry Andric bool verifyInstruction(const MachineInstr &MI, 60981ad6265SDimitry Andric StringRef &ErrInfo) const override; 6100b57cec5SDimitry Andric #define GET_INSTRINFO_HELPER_DECLS 6110b57cec5SDimitry Andric #include "X86GenInstrInfo.inc" 6120b57cec5SDimitry Andric 6138bcb0991SDimitry Andric static bool hasLockPrefix(const MachineInstr &MI) { 6148bcb0991SDimitry Andric return MI.getDesc().TSFlags & X86II::LOCK; 6158bcb0991SDimitry Andric } 6168bcb0991SDimitry Andric 617bdd1243dSDimitry Andric std::optional<ParamLoadedValue> 618bdd1243dSDimitry Andric describeLoadedValue(const MachineInstr &MI, Register Reg) const override; 6198bcb0991SDimitry Andric 6200b57cec5SDimitry Andric protected: 6210b57cec5SDimitry Andric MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 6220b57cec5SDimitry Andric unsigned CommuteOpIdx1, 6230b57cec5SDimitry Andric unsigned CommuteOpIdx2) const override; 6240b57cec5SDimitry Andric 625bdd1243dSDimitry Andric std::optional<DestSourcePair> 626480093f4SDimitry Andric isCopyInstrImpl(const MachineInstr &MI) const override; 6270b57cec5SDimitry Andric 628*0fca6ea1SDimitry Andric bool getMachineCombinerPatterns(MachineInstr &Root, 629*0fca6ea1SDimitry Andric SmallVectorImpl<unsigned> &Patterns, 63006c3fb27SDimitry Andric bool DoRegPressureReduce) const override; 63106c3fb27SDimitry Andric 63206c3fb27SDimitry Andric /// When getMachineCombinerPatterns() finds potential patterns, 63306c3fb27SDimitry Andric /// this function generates the instructions that could replace the 63406c3fb27SDimitry Andric /// original code sequence. 63506c3fb27SDimitry Andric void genAlternativeCodeSequence( 636*0fca6ea1SDimitry Andric MachineInstr &Root, unsigned Pattern, 63706c3fb27SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs, 63806c3fb27SDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs, 63906c3fb27SDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override; 64006c3fb27SDimitry Andric 64106c3fb27SDimitry Andric /// When calculate the latency of the root instruction, accumulate the 64206c3fb27SDimitry Andric /// latency of the sequence to the root latency. 64306c3fb27SDimitry Andric /// \param Root - Instruction that could be combined with one of its operands 64406c3fb27SDimitry Andric /// For X86 instruction (vpmaddwd + vpmaddwd) -> vpdpwssd, the vpmaddwd 64506c3fb27SDimitry Andric /// is not in the critical path, so the root latency only include vpmaddwd. 64606c3fb27SDimitry Andric bool accumulateInstrSeqToRootLatency(MachineInstr &Root) const override { 64706c3fb27SDimitry Andric return false; 64806c3fb27SDimitry Andric } 64906c3fb27SDimitry Andric 6505f757f3fSDimitry Andric void getFrameIndexOperands(SmallVectorImpl<MachineOperand> &Ops, 6515f757f3fSDimitry Andric int FI) const override; 6525f757f3fSDimitry Andric 6530b57cec5SDimitry Andric private: 6540b57cec5SDimitry Andric /// This is a helper for convertToThreeAddress for 8 and 16-bit instructions. 6550b57cec5SDimitry Andric /// We use 32-bit LEA to form 3-address code by promoting to a 32-bit 6560b57cec5SDimitry Andric /// super-register and then truncating back down to a 8/16-bit sub-register. 657349cc55cSDimitry Andric MachineInstr *convertToThreeAddressWithLEA(unsigned MIOpc, MachineInstr &MI, 6580b57cec5SDimitry Andric LiveVariables *LV, 659349cc55cSDimitry Andric LiveIntervals *LIS, 6600b57cec5SDimitry Andric bool Is8BitOp) const; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric /// Handles memory folding for special case instructions, for instance those 6630b57cec5SDimitry Andric /// requiring custom manipulation of the address. 6640b57cec5SDimitry Andric MachineInstr *foldMemoryOperandCustom(MachineFunction &MF, MachineInstr &MI, 6650b57cec5SDimitry Andric unsigned OpNum, 6660b57cec5SDimitry Andric ArrayRef<MachineOperand> MOs, 6670b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPt, 6685ffd83dbSDimitry Andric unsigned Size, Align Alignment) const; 6690b57cec5SDimitry Andric 670*0fca6ea1SDimitry Andric MachineInstr *foldMemoryBroadcast(MachineFunction &MF, MachineInstr &MI, 671*0fca6ea1SDimitry Andric unsigned OpNum, 672*0fca6ea1SDimitry Andric ArrayRef<MachineOperand> MOs, 673*0fca6ea1SDimitry Andric MachineBasicBlock::iterator InsertPt, 674*0fca6ea1SDimitry Andric unsigned BitsSize, bool AllowCommute) const; 675*0fca6ea1SDimitry Andric 6760b57cec5SDimitry Andric /// isFrameOperand - Return true and the FrameIndex if the specified 6770b57cec5SDimitry Andric /// operand and follow operands form a reference to the stack frame. 6780b57cec5SDimitry Andric bool isFrameOperand(const MachineInstr &MI, unsigned int Op, 6790b57cec5SDimitry Andric int &FrameIndex) const; 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric /// Returns true iff the routine could find two commutable operands in the 6820b57cec5SDimitry Andric /// given machine instruction with 3 vector inputs. 6830b57cec5SDimitry Andric /// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. Their 6840b57cec5SDimitry Andric /// input values can be re-defined in this method only if the input values 6850b57cec5SDimitry Andric /// are not pre-defined, which is designated by the special value 6860b57cec5SDimitry Andric /// 'CommuteAnyOperandIndex' assigned to it. 6870b57cec5SDimitry Andric /// If both of indices are pre-defined and refer to some operands, then the 6880b57cec5SDimitry Andric /// method simply returns true if the corresponding operands are commutable 6890b57cec5SDimitry Andric /// and returns false otherwise. 6900b57cec5SDimitry Andric /// 6910b57cec5SDimitry Andric /// For example, calling this method this way: 6920b57cec5SDimitry Andric /// unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex; 6930b57cec5SDimitry Andric /// findThreeSrcCommutedOpIndices(MI, Op1, Op2); 6940b57cec5SDimitry Andric /// can be interpreted as a query asking to find an operand that would be 6950b57cec5SDimitry Andric /// commutable with the operand#1. 6960b57cec5SDimitry Andric /// 6970b57cec5SDimitry Andric /// If IsIntrinsic is set, operand 1 will be ignored for commuting. 6980b57cec5SDimitry Andric bool findThreeSrcCommutedOpIndices(const MachineInstr &MI, 6990b57cec5SDimitry Andric unsigned &SrcOpIdx1, 7000b57cec5SDimitry Andric unsigned &SrcOpIdx2, 7010b57cec5SDimitry Andric bool IsIntrinsic = false) const; 702349cc55cSDimitry Andric 703349cc55cSDimitry Andric /// Returns true when instruction \p FlagI produces the same flags as \p OI. 704349cc55cSDimitry Andric /// The caller should pass in the results of calling analyzeCompare on \p OI: 705349cc55cSDimitry Andric /// \p SrcReg, \p SrcReg2, \p ImmMask, \p ImmValue. 706349cc55cSDimitry Andric /// If the flags match \p OI as if it had the input operands swapped then the 707349cc55cSDimitry Andric /// function succeeds and sets \p IsSwapped to true. 708349cc55cSDimitry Andric /// 709349cc55cSDimitry Andric /// Examples of OI, FlagI pairs returning true: 710349cc55cSDimitry Andric /// CMP %1, 42 and CMP %1, 42 711349cc55cSDimitry Andric /// CMP %1, %2 and %3 = SUB %1, %2 712349cc55cSDimitry Andric /// TEST %1, %1 and %2 = SUB %1, 0 713349cc55cSDimitry Andric /// CMP %1, %2 and %3 = SUB %2, %1 ; IsSwapped=true 714349cc55cSDimitry Andric bool isRedundantFlagInstr(const MachineInstr &FlagI, Register SrcReg, 715349cc55cSDimitry Andric Register SrcReg2, int64_t ImmMask, int64_t ImmValue, 71604eeddc0SDimitry Andric const MachineInstr &OI, bool *IsSwapped, 71704eeddc0SDimitry Andric int64_t *ImmDelta) const; 7180b57cec5SDimitry Andric 719*0fca6ea1SDimitry Andric /// Commute operands of \p MI for memory fold. 720*0fca6ea1SDimitry Andric /// 721*0fca6ea1SDimitry Andric /// \param Idx1 the index of operand to be commuted. 722*0fca6ea1SDimitry Andric /// 723*0fca6ea1SDimitry Andric /// \returns the index of operand that is commuted with \p Idx1. If the method 724*0fca6ea1SDimitry Andric /// fails to commute the operands, it will return \p Idx1. 725*0fca6ea1SDimitry Andric unsigned commuteOperandsForFold(MachineInstr &MI, unsigned Idx1) const; 726*0fca6ea1SDimitry Andric }; 7270b57cec5SDimitry Andric } // namespace llvm 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric #endif 730