xref: /openbsd-src/gnu/llvm/llvm/lib/Target/X86/X86InstrInfo.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- X86InstrInfo.h - X86 Instruction Information ------------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains the X86 implementation of the TargetInstrInfo class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #ifndef LLVM_LIB_TARGET_X86_X86INSTRINFO_H
1409467b48Spatrick #define LLVM_LIB_TARGET_X86_X86INSTRINFO_H
1509467b48Spatrick 
1609467b48Spatrick #include "MCTargetDesc/X86BaseInfo.h"
1709467b48Spatrick #include "X86InstrFMA3Info.h"
1809467b48Spatrick #include "X86RegisterInfo.h"
1909467b48Spatrick #include "llvm/CodeGen/ISDOpcodes.h"
2009467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
2109467b48Spatrick #include <vector>
2209467b48Spatrick 
2309467b48Spatrick #define GET_INSTRINFO_HEADER
2409467b48Spatrick #include "X86GenInstrInfo.inc"
2509467b48Spatrick 
2609467b48Spatrick namespace llvm {
2709467b48Spatrick class X86Subtarget;
2809467b48Spatrick 
2909467b48Spatrick namespace X86 {
3009467b48Spatrick 
3109467b48Spatrick enum AsmComments {
3209467b48Spatrick   // For instr that was compressed from EVEX to VEX.
3309467b48Spatrick   AC_EVEX_2_VEX = MachineInstr::TAsmComments
3409467b48Spatrick };
3509467b48Spatrick 
3609467b48Spatrick /// Return a pair of condition code for the given predicate and whether
3709467b48Spatrick /// the instruction operands should be swaped to match the condition code.
3809467b48Spatrick std::pair<CondCode, bool> getX86ConditionCode(CmpInst::Predicate Predicate);
3909467b48Spatrick 
4009467b48Spatrick /// Return a cmov opcode for the given register size in bytes, and operand type.
4109467b48Spatrick unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand = false);
4209467b48Spatrick 
43*d415bd75Srobert /// Return the source operand # for condition code by \p MCID. If the
44*d415bd75Srobert /// instruction doesn't have a condition code, return -1.
45*d415bd75Srobert int getCondSrcNoFromDesc(const MCInstrDesc &MCID);
46*d415bd75Srobert 
47*d415bd75Srobert /// Return the condition code of the instruction. If the instruction doesn't
48*d415bd75Srobert /// have a condition code, return X86::COND_INVALID.
49*d415bd75Srobert CondCode getCondFromMI(const MachineInstr &MI);
50*d415bd75Srobert 
51*d415bd75Srobert // Turn JCC instruction into condition code.
5209467b48Spatrick CondCode getCondFromBranch(const MachineInstr &MI);
5309467b48Spatrick 
54*d415bd75Srobert // Turn SETCC instruction into condition code.
5509467b48Spatrick CondCode getCondFromSETCC(const MachineInstr &MI);
5609467b48Spatrick 
57*d415bd75Srobert // Turn CMOV instruction into condition code.
5809467b48Spatrick CondCode getCondFromCMov(const MachineInstr &MI);
5909467b48Spatrick 
6009467b48Spatrick /// GetOppositeBranchCondition - Return the inverse of the specified cond,
6109467b48Spatrick /// e.g. turning COND_E to COND_NE.
6209467b48Spatrick CondCode GetOppositeBranchCondition(CondCode CC);
6309467b48Spatrick 
6409467b48Spatrick /// Get the VPCMP immediate for the given condition.
6509467b48Spatrick unsigned getVPCMPImmForCond(ISD::CondCode CC);
6609467b48Spatrick 
6709467b48Spatrick /// Get the VPCMP immediate if the opcodes are swapped.
6809467b48Spatrick unsigned getSwappedVPCMPImm(unsigned Imm);
6909467b48Spatrick 
7009467b48Spatrick /// Get the VPCOM immediate if the opcodes are swapped.
7109467b48Spatrick unsigned getSwappedVPCOMImm(unsigned Imm);
7209467b48Spatrick 
7309467b48Spatrick /// Get the VCMP immediate if the opcodes are swapped.
7409467b48Spatrick unsigned getSwappedVCMPImm(unsigned Imm);
7509467b48Spatrick 
76*d415bd75Srobert /// Check if the instruction is X87 instruction.
77*d415bd75Srobert bool isX87Instruction(MachineInstr &MI);
7809467b48Spatrick } // namespace X86
7909467b48Spatrick 
8009467b48Spatrick /// isGlobalStubReference - Return true if the specified TargetFlag operand is
8109467b48Spatrick /// a reference to a stub for a global, not the global itself.
isGlobalStubReference(unsigned char TargetFlag)8209467b48Spatrick inline static bool isGlobalStubReference(unsigned char TargetFlag) {
8309467b48Spatrick   switch (TargetFlag) {
8409467b48Spatrick   case X86II::MO_DLLIMPORT:               // dllimport stub.
8509467b48Spatrick   case X86II::MO_GOTPCREL:                // rip-relative GOT reference.
86*d415bd75Srobert   case X86II::MO_GOTPCREL_NORELAX:        // rip-relative GOT reference.
8709467b48Spatrick   case X86II::MO_GOT:                     // normal GOT reference.
8809467b48Spatrick   case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref.
8909467b48Spatrick   case X86II::MO_DARWIN_NONLAZY:          // Normal $non_lazy_ptr ref.
9009467b48Spatrick   case X86II::MO_COFFSTUB:                // COFF .refptr stub.
9109467b48Spatrick     return true;
9209467b48Spatrick   default:
9309467b48Spatrick     return false;
9409467b48Spatrick   }
9509467b48Spatrick }
9609467b48Spatrick 
9709467b48Spatrick /// isGlobalRelativeToPICBase - Return true if the specified global value
9809467b48Spatrick /// reference is relative to a 32-bit PIC base (X86ISD::GlobalBaseReg).  If this
9909467b48Spatrick /// is true, the addressing mode has the PIC base register added in (e.g. EBX).
isGlobalRelativeToPICBase(unsigned char TargetFlag)10009467b48Spatrick inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
10109467b48Spatrick   switch (TargetFlag) {
10209467b48Spatrick   case X86II::MO_GOTOFF:                  // isPICStyleGOT: local global.
10309467b48Spatrick   case X86II::MO_GOT:                     // isPICStyleGOT: other global.
10409467b48Spatrick   case X86II::MO_PIC_BASE_OFFSET:         // Darwin local global.
10509467b48Spatrick   case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global.
10609467b48Spatrick   case X86II::MO_TLVP:                    // ??? Pretty sure..
10709467b48Spatrick     return true;
10809467b48Spatrick   default:
10909467b48Spatrick     return false;
11009467b48Spatrick   }
11109467b48Spatrick }
11209467b48Spatrick 
isScale(const MachineOperand & MO)11309467b48Spatrick inline static bool isScale(const MachineOperand &MO) {
11409467b48Spatrick   return MO.isImm() && (MO.getImm() == 1 || MO.getImm() == 2 ||
11509467b48Spatrick                         MO.getImm() == 4 || MO.getImm() == 8);
11609467b48Spatrick }
11709467b48Spatrick 
isLeaMem(const MachineInstr & MI,unsigned Op)11809467b48Spatrick inline static bool isLeaMem(const MachineInstr &MI, unsigned Op) {
11909467b48Spatrick   if (MI.getOperand(Op).isFI())
12009467b48Spatrick     return true;
12109467b48Spatrick   return Op + X86::AddrSegmentReg <= MI.getNumOperands() &&
12209467b48Spatrick          MI.getOperand(Op + X86::AddrBaseReg).isReg() &&
12309467b48Spatrick          isScale(MI.getOperand(Op + X86::AddrScaleAmt)) &&
12409467b48Spatrick          MI.getOperand(Op + X86::AddrIndexReg).isReg() &&
12509467b48Spatrick          (MI.getOperand(Op + X86::AddrDisp).isImm() ||
12609467b48Spatrick           MI.getOperand(Op + X86::AddrDisp).isGlobal() ||
12709467b48Spatrick           MI.getOperand(Op + X86::AddrDisp).isCPI() ||
12809467b48Spatrick           MI.getOperand(Op + X86::AddrDisp).isJTI());
12909467b48Spatrick }
13009467b48Spatrick 
isMem(const MachineInstr & MI,unsigned Op)13109467b48Spatrick inline static bool isMem(const MachineInstr &MI, unsigned Op) {
13209467b48Spatrick   if (MI.getOperand(Op).isFI())
13309467b48Spatrick     return true;
13409467b48Spatrick   return Op + X86::AddrNumOperands <= MI.getNumOperands() &&
13509467b48Spatrick          MI.getOperand(Op + X86::AddrSegmentReg).isReg() && isLeaMem(MI, Op);
13609467b48Spatrick }
13709467b48Spatrick 
13809467b48Spatrick class X86InstrInfo final : public X86GenInstrInfo {
13909467b48Spatrick   X86Subtarget &Subtarget;
14009467b48Spatrick   const X86RegisterInfo RI;
14109467b48Spatrick 
14209467b48Spatrick   virtual void anchor();
14309467b48Spatrick 
14409467b48Spatrick   bool AnalyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
14509467b48Spatrick                          MachineBasicBlock *&FBB,
14609467b48Spatrick                          SmallVectorImpl<MachineOperand> &Cond,
14709467b48Spatrick                          SmallVectorImpl<MachineInstr *> &CondBranches,
14809467b48Spatrick                          bool AllowModify) const;
14909467b48Spatrick 
15009467b48Spatrick public:
15109467b48Spatrick   explicit X86InstrInfo(X86Subtarget &STI);
15209467b48Spatrick 
15309467b48Spatrick   /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
15409467b48Spatrick   /// such, whenever a client has an instance of instruction info, it should
15509467b48Spatrick   /// always be able to get register info as well (through this method).
15609467b48Spatrick   ///
getRegisterInfo()15709467b48Spatrick   const X86RegisterInfo &getRegisterInfo() const { return RI; }
15809467b48Spatrick 
15909467b48Spatrick   /// Returns the stack pointer adjustment that happens inside the frame
16009467b48Spatrick   /// setup..destroy sequence (e.g. by pushes, or inside the callee).
getFrameAdjustment(const MachineInstr & I)16109467b48Spatrick   int64_t getFrameAdjustment(const MachineInstr &I) const {
16209467b48Spatrick     assert(isFrameInstr(I));
16309467b48Spatrick     if (isFrameSetup(I))
16409467b48Spatrick       return I.getOperand(2).getImm();
16509467b48Spatrick     return I.getOperand(1).getImm();
16609467b48Spatrick   }
16709467b48Spatrick 
16809467b48Spatrick   /// Sets the stack pointer adjustment made inside the frame made up by this
16909467b48Spatrick   /// instruction.
setFrameAdjustment(MachineInstr & I,int64_t V)17009467b48Spatrick   void setFrameAdjustment(MachineInstr &I, int64_t V) const {
17109467b48Spatrick     assert(isFrameInstr(I));
17209467b48Spatrick     if (isFrameSetup(I))
17309467b48Spatrick       I.getOperand(2).setImm(V);
17409467b48Spatrick     else
17509467b48Spatrick       I.getOperand(1).setImm(V);
17609467b48Spatrick   }
17709467b48Spatrick 
17809467b48Spatrick   /// getSPAdjust - This returns the stack pointer adjustment made by
17909467b48Spatrick   /// this instruction. For x86, we need to handle more complex call
18009467b48Spatrick   /// sequences involving PUSHes.
18109467b48Spatrick   int getSPAdjust(const MachineInstr &MI) const override;
18209467b48Spatrick 
18309467b48Spatrick   /// isCoalescableExtInstr - Return true if the instruction is a "coalescable"
18409467b48Spatrick   /// extension instruction. That is, it's like a copy where it's legal for the
18509467b48Spatrick   /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns
18609467b48Spatrick   /// true, then it's expected the pre-extension value is available as a subreg
18709467b48Spatrick   /// of the result register. This also returns the sub-register index in
18809467b48Spatrick   /// SubIdx.
189097a140dSpatrick   bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg,
190097a140dSpatrick                              Register &DstReg, unsigned &SubIdx) const override;
191097a140dSpatrick 
192097a140dSpatrick   /// Returns true if the instruction has no behavior (specified or otherwise)
193097a140dSpatrick   /// that is based on the value of any of its register operands
194097a140dSpatrick   ///
195097a140dSpatrick   /// Instructions are considered data invariant even if they set EFLAGS.
196097a140dSpatrick   ///
197097a140dSpatrick   /// A classical example of something that is inherently not data invariant is
198097a140dSpatrick   /// an indirect jump -- the destination is loaded into icache based on the
199097a140dSpatrick   /// bits set in the jump destination register.
200097a140dSpatrick   ///
201097a140dSpatrick   /// FIXME: This should become part of our instruction tables.
202097a140dSpatrick   static bool isDataInvariant(MachineInstr &MI);
203097a140dSpatrick 
204097a140dSpatrick   /// Returns true if the instruction has no behavior (specified or otherwise)
205097a140dSpatrick   /// that is based on the value loaded from memory or the value of any
206097a140dSpatrick   /// non-address register operands.
207097a140dSpatrick   ///
208097a140dSpatrick   /// For example, if the latency of the instruction is dependent on the
209097a140dSpatrick   /// particular bits set in any of the registers *or* any of the bits loaded
210097a140dSpatrick   /// from memory.
211097a140dSpatrick   ///
212097a140dSpatrick   /// Instructions are considered data invariant even if they set EFLAGS.
213097a140dSpatrick   ///
214097a140dSpatrick   /// A classical example of something that is inherently not data invariant is
215097a140dSpatrick   /// an indirect jump -- the destination is loaded into icache based on the
216097a140dSpatrick   /// bits set in the jump destination register.
217097a140dSpatrick   ///
218097a140dSpatrick   /// FIXME: This should become part of our instruction tables.
219097a140dSpatrick   static bool isDataInvariantLoad(MachineInstr &MI);
22009467b48Spatrick 
22109467b48Spatrick   unsigned isLoadFromStackSlot(const MachineInstr &MI,
22209467b48Spatrick                                int &FrameIndex) const override;
22309467b48Spatrick   unsigned isLoadFromStackSlot(const MachineInstr &MI,
22409467b48Spatrick                                int &FrameIndex,
22509467b48Spatrick                                unsigned &MemBytes) const override;
22609467b48Spatrick   /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination
22709467b48Spatrick   /// stack locations as well.  This uses a heuristic so it isn't
22809467b48Spatrick   /// reliable for correctness.
22909467b48Spatrick   unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI,
23009467b48Spatrick                                      int &FrameIndex) const override;
23109467b48Spatrick 
23209467b48Spatrick   unsigned isStoreToStackSlot(const MachineInstr &MI,
23309467b48Spatrick                               int &FrameIndex) const override;
23409467b48Spatrick   unsigned isStoreToStackSlot(const MachineInstr &MI,
23509467b48Spatrick                               int &FrameIndex,
23609467b48Spatrick                               unsigned &MemBytes) const override;
23709467b48Spatrick   /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination
23809467b48Spatrick   /// stack locations as well.  This uses a heuristic so it isn't
23909467b48Spatrick   /// reliable for correctness.
24009467b48Spatrick   unsigned isStoreToStackSlotPostFE(const MachineInstr &MI,
24109467b48Spatrick                                     int &FrameIndex) const override;
24209467b48Spatrick 
243*d415bd75Srobert   bool isReallyTriviallyReMaterializable(const MachineInstr &MI) const override;
24409467b48Spatrick   void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
245097a140dSpatrick                      Register DestReg, unsigned SubIdx,
24609467b48Spatrick                      const MachineInstr &Orig,
24709467b48Spatrick                      const TargetRegisterInfo &TRI) const override;
24809467b48Spatrick 
24909467b48Spatrick   /// Given an operand within a MachineInstr, insert preceding code to put it
25009467b48Spatrick   /// into the right format for a particular kind of LEA instruction. This may
25109467b48Spatrick   /// involve using an appropriate super-register instead (with an implicit use
25209467b48Spatrick   /// of the original) or creating a new virtual register and inserting COPY
25309467b48Spatrick   /// instructions to get the data into the right class.
25409467b48Spatrick   ///
25509467b48Spatrick   /// Reference parameters are set to indicate how caller should add this
25609467b48Spatrick   /// operand to the LEA instruction.
25709467b48Spatrick   bool classifyLEAReg(MachineInstr &MI, const MachineOperand &Src,
25809467b48Spatrick                       unsigned LEAOpcode, bool AllowSP, Register &NewSrc,
25909467b48Spatrick                       bool &isKill, MachineOperand &ImplicitOp,
260*d415bd75Srobert                       LiveVariables *LV, LiveIntervals *LIS) const;
26109467b48Spatrick 
26209467b48Spatrick   /// convertToThreeAddress - This method must be implemented by targets that
26309467b48Spatrick   /// set the M_CONVERTIBLE_TO_3_ADDR flag.  When this flag is set, the target
26409467b48Spatrick   /// may be able to convert a two-address instruction into a true
26509467b48Spatrick   /// three-address instruction on demand.  This allows the X86 target (for
26609467b48Spatrick   /// example) to convert ADD and SHL instructions into LEA instructions if they
26709467b48Spatrick   /// would require register copies due to two-addressness.
26809467b48Spatrick   ///
26909467b48Spatrick   /// This method returns a null pointer if the transformation cannot be
27009467b48Spatrick   /// performed, otherwise it returns the new instruction.
27109467b48Spatrick   ///
272*d415bd75Srobert   MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
273*d415bd75Srobert                                       LiveIntervals *LIS) const override;
27409467b48Spatrick 
27509467b48Spatrick   /// Returns true iff the routine could find two commutable operands in the
27609467b48Spatrick   /// given machine instruction.
27709467b48Spatrick   /// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. Their
27809467b48Spatrick   /// input values can be re-defined in this method only if the input values
27909467b48Spatrick   /// are not pre-defined, which is designated by the special value
28009467b48Spatrick   /// 'CommuteAnyOperandIndex' assigned to it.
28109467b48Spatrick   /// If both of indices are pre-defined and refer to some operands, then the
28209467b48Spatrick   /// method simply returns true if the corresponding operands are commutable
28309467b48Spatrick   /// and returns false otherwise.
28409467b48Spatrick   ///
28509467b48Spatrick   /// For example, calling this method this way:
28609467b48Spatrick   ///     unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex;
28709467b48Spatrick   ///     findCommutedOpIndices(MI, Op1, Op2);
28809467b48Spatrick   /// can be interpreted as a query asking to find an operand that would be
28909467b48Spatrick   /// commutable with the operand#1.
29009467b48Spatrick   bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
29109467b48Spatrick                              unsigned &SrcOpIdx2) const override;
29209467b48Spatrick 
29373471bf0Spatrick   /// Returns true if we have preference on the operands order in MI, the
29473471bf0Spatrick   /// commute decision is returned in Commute.
29573471bf0Spatrick   bool hasCommutePreference(MachineInstr &MI, bool &Commute) const override;
29673471bf0Spatrick 
29709467b48Spatrick   /// Returns an adjusted FMA opcode that must be used in FMA instruction that
29809467b48Spatrick   /// performs the same computations as the given \p MI but which has the
29909467b48Spatrick   /// operands \p SrcOpIdx1 and \p SrcOpIdx2 commuted.
30009467b48Spatrick   /// It may return 0 if it is unsafe to commute the operands.
30109467b48Spatrick   /// Note that a machine instruction (instead of its opcode) is passed as the
30209467b48Spatrick   /// first parameter to make it possible to analyze the instruction's uses and
30309467b48Spatrick   /// commute the first operand of FMA even when it seems unsafe when you look
30409467b48Spatrick   /// at the opcode. For example, it is Ok to commute the first operand of
30509467b48Spatrick   /// VFMADD*SD_Int, if ONLY the lowest 64-bit element of the result is used.
30609467b48Spatrick   ///
30709467b48Spatrick   /// The returned FMA opcode may differ from the opcode in the given \p MI.
30809467b48Spatrick   /// For example, commuting the operands #1 and #3 in the following FMA
30909467b48Spatrick   ///     FMA213 #1, #2, #3
31009467b48Spatrick   /// results into instruction with adjusted opcode:
31109467b48Spatrick   ///     FMA231 #3, #2, #1
31209467b48Spatrick   unsigned
31309467b48Spatrick   getFMA3OpcodeToCommuteOperands(const MachineInstr &MI, unsigned SrcOpIdx1,
31409467b48Spatrick                                  unsigned SrcOpIdx2,
31509467b48Spatrick                                  const X86InstrFMA3Group &FMA3Group) const;
31609467b48Spatrick 
31709467b48Spatrick   // Branch analysis.
31809467b48Spatrick   bool isUnconditionalTailCall(const MachineInstr &MI) const override;
31909467b48Spatrick   bool canMakeTailCallConditional(SmallVectorImpl<MachineOperand> &Cond,
32009467b48Spatrick                                   const MachineInstr &TailCall) const override;
32109467b48Spatrick   void replaceBranchWithTailCall(MachineBasicBlock &MBB,
32209467b48Spatrick                                  SmallVectorImpl<MachineOperand> &Cond,
32309467b48Spatrick                                  const MachineInstr &TailCall) const override;
32409467b48Spatrick 
32509467b48Spatrick   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
32609467b48Spatrick                      MachineBasicBlock *&FBB,
32709467b48Spatrick                      SmallVectorImpl<MachineOperand> &Cond,
32809467b48Spatrick                      bool AllowModify) const override;
32909467b48Spatrick 
330*d415bd75Srobert   std::optional<ExtAddrMode>
33173471bf0Spatrick   getAddrModeFromMemoryOp(const MachineInstr &MemI,
33273471bf0Spatrick                           const TargetRegisterInfo *TRI) const override;
33373471bf0Spatrick 
33473471bf0Spatrick   bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg,
33573471bf0Spatrick                                int64_t &ImmVal) const override;
33673471bf0Spatrick 
33773471bf0Spatrick   bool preservesZeroValueInReg(const MachineInstr *MI,
33873471bf0Spatrick                                const Register NullValueReg,
33973471bf0Spatrick                                const TargetRegisterInfo *TRI) const override;
34073471bf0Spatrick 
341097a140dSpatrick   bool getMemOperandsWithOffsetWidth(
342097a140dSpatrick       const MachineInstr &LdSt,
343097a140dSpatrick       SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset,
344097a140dSpatrick       bool &OffsetIsScalable, unsigned &Width,
34509467b48Spatrick       const TargetRegisterInfo *TRI) const override;
34609467b48Spatrick   bool analyzeBranchPredicate(MachineBasicBlock &MBB,
34709467b48Spatrick                               TargetInstrInfo::MachineBranchPredicate &MBP,
34809467b48Spatrick                               bool AllowModify = false) const override;
34909467b48Spatrick 
35009467b48Spatrick   unsigned removeBranch(MachineBasicBlock &MBB,
35109467b48Spatrick                         int *BytesRemoved = nullptr) const override;
35209467b48Spatrick   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
35309467b48Spatrick                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
35409467b48Spatrick                         const DebugLoc &DL,
35509467b48Spatrick                         int *BytesAdded = nullptr) const override;
35609467b48Spatrick   bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
357097a140dSpatrick                        Register, Register, Register, int &, int &,
358097a140dSpatrick                        int &) const override;
35909467b48Spatrick   void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
360097a140dSpatrick                     const DebugLoc &DL, Register DstReg,
361097a140dSpatrick                     ArrayRef<MachineOperand> Cond, Register TrueReg,
362097a140dSpatrick                     Register FalseReg) const override;
36309467b48Spatrick   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
36409467b48Spatrick                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
36509467b48Spatrick                    bool KillSrc) const override;
36609467b48Spatrick   void storeRegToStackSlot(MachineBasicBlock &MBB,
367097a140dSpatrick                            MachineBasicBlock::iterator MI, Register SrcReg,
36809467b48Spatrick                            bool isKill, int FrameIndex,
36909467b48Spatrick                            const TargetRegisterClass *RC,
370*d415bd75Srobert                            const TargetRegisterInfo *TRI,
371*d415bd75Srobert                            Register VReg) const override;
37209467b48Spatrick 
37309467b48Spatrick   void loadRegFromStackSlot(MachineBasicBlock &MBB,
374097a140dSpatrick                             MachineBasicBlock::iterator MI, Register DestReg,
37509467b48Spatrick                             int FrameIndex, const TargetRegisterClass *RC,
376*d415bd75Srobert                             const TargetRegisterInfo *TRI,
377*d415bd75Srobert                             Register VReg) const override;
378*d415bd75Srobert 
379*d415bd75Srobert   void loadStoreTileReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
380*d415bd75Srobert                         unsigned Opc, Register Reg, int FrameIdx,
381*d415bd75Srobert                         bool isKill = false) const;
38209467b48Spatrick 
38309467b48Spatrick   bool expandPostRAPseudo(MachineInstr &MI) const override;
38409467b48Spatrick 
38509467b48Spatrick   /// Check whether the target can fold a load that feeds a subreg operand
38609467b48Spatrick   /// (or a subreg operand that feeds a store).
isSubregFoldable()38709467b48Spatrick   bool isSubregFoldable() const override { return true; }
38809467b48Spatrick 
38909467b48Spatrick   /// foldMemoryOperand - If this target supports it, fold a load or store of
39009467b48Spatrick   /// the specified stack slot into the specified machine instruction for the
39109467b48Spatrick   /// specified operand(s).  If this is possible, the target should perform the
39209467b48Spatrick   /// folding and return true, otherwise it should return false.  If it folds
39309467b48Spatrick   /// the instruction, it is likely that the MachineInstruction the iterator
39409467b48Spatrick   /// references has been changed.
39509467b48Spatrick   MachineInstr *
39609467b48Spatrick   foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
39709467b48Spatrick                         ArrayRef<unsigned> Ops,
39809467b48Spatrick                         MachineBasicBlock::iterator InsertPt, int FrameIndex,
39909467b48Spatrick                         LiveIntervals *LIS = nullptr,
40009467b48Spatrick                         VirtRegMap *VRM = nullptr) const override;
40109467b48Spatrick 
40209467b48Spatrick   /// foldMemoryOperand - Same as the previous version except it allows folding
40309467b48Spatrick   /// of any load and store from / to any address, not just from a specific
40409467b48Spatrick   /// stack slot.
40509467b48Spatrick   MachineInstr *foldMemoryOperandImpl(
40609467b48Spatrick       MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
40709467b48Spatrick       MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
40809467b48Spatrick       LiveIntervals *LIS = nullptr) const override;
40909467b48Spatrick 
41009467b48Spatrick   /// unfoldMemoryOperand - Separate a single instruction which folded a load or
41109467b48Spatrick   /// a store or a load and a store into two or more instruction. If this is
41209467b48Spatrick   /// possible, returns true as well as the new instructions by reference.
41309467b48Spatrick   bool
41409467b48Spatrick   unfoldMemoryOperand(MachineFunction &MF, MachineInstr &MI, unsigned Reg,
41509467b48Spatrick                       bool UnfoldLoad, bool UnfoldStore,
41609467b48Spatrick                       SmallVectorImpl<MachineInstr *> &NewMIs) const override;
41709467b48Spatrick 
41809467b48Spatrick   bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
41909467b48Spatrick                            SmallVectorImpl<SDNode *> &NewNodes) const override;
42009467b48Spatrick 
42109467b48Spatrick   /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new
42209467b48Spatrick   /// instruction after load / store are unfolded from an instruction of the
42309467b48Spatrick   /// specified opcode. It returns zero if the specified unfolding is not
42409467b48Spatrick   /// possible. If LoadRegIndex is non-null, it is filled in with the operand
42509467b48Spatrick   /// index of the operand which will hold the register holding the loaded
42609467b48Spatrick   /// value.
42709467b48Spatrick   unsigned
42809467b48Spatrick   getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore,
42909467b48Spatrick                              unsigned *LoadRegIndex = nullptr) const override;
43009467b48Spatrick 
43109467b48Spatrick   /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler
43209467b48Spatrick   /// to determine if two loads are loading from the same base address. It
43309467b48Spatrick   /// should only return true if the base pointers are the same and the
43409467b48Spatrick   /// only differences between the two addresses are the offset. It also returns
43509467b48Spatrick   /// the offsets by reference.
43609467b48Spatrick   bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1,
43709467b48Spatrick                                int64_t &Offset2) const override;
43809467b48Spatrick 
43973471bf0Spatrick   /// isSchedulingBoundary - Overrides the isSchedulingBoundary from
44073471bf0Spatrick   ///	Codegen/TargetInstrInfo.cpp to make it capable of identifying ENDBR
44173471bf0Spatrick   /// intructions and prevent it from being re-scheduled.
44273471bf0Spatrick   bool isSchedulingBoundary(const MachineInstr &MI,
44373471bf0Spatrick                             const MachineBasicBlock *MBB,
44473471bf0Spatrick                             const MachineFunction &MF) const override;
44573471bf0Spatrick 
44609467b48Spatrick   /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to
44709467b48Spatrick   /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads
44809467b48Spatrick   /// should be scheduled togther. On some targets if two loads are loading from
44909467b48Spatrick   /// addresses in the same cache line, it's better if they are scheduled
45009467b48Spatrick   /// together. This function takes two integers that represent the load offsets
45109467b48Spatrick   /// from the common base address. It returns true if it decides it's desirable
45209467b48Spatrick   /// to schedule the two loads together. "NumLoads" is the number of loads that
45309467b48Spatrick   /// have already been scheduled after Load1.
45409467b48Spatrick   bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1,
45509467b48Spatrick                                int64_t Offset2,
45609467b48Spatrick                                unsigned NumLoads) const override;
45709467b48Spatrick 
45873471bf0Spatrick   MCInst getNop() const override;
45909467b48Spatrick 
46009467b48Spatrick   bool
46109467b48Spatrick   reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
46209467b48Spatrick 
46309467b48Spatrick   /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine
46409467b48Spatrick   /// instruction that defines the specified register class.
46509467b48Spatrick   bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const override;
46609467b48Spatrick 
46709467b48Spatrick   /// True if MI has a condition code def, e.g. EFLAGS, that is
46809467b48Spatrick   /// not marked dead.
46909467b48Spatrick   bool hasLiveCondCodeDef(MachineInstr &MI) const;
47009467b48Spatrick 
47109467b48Spatrick   /// getGlobalBaseReg - Return a virtual register initialized with the
47209467b48Spatrick   /// the global base register value. Output instructions required to
47309467b48Spatrick   /// initialize the register in the function entry block, if necessary.
47409467b48Spatrick   ///
47509467b48Spatrick   unsigned getGlobalBaseReg(MachineFunction *MF) const;
47609467b48Spatrick 
47709467b48Spatrick   std::pair<uint16_t, uint16_t>
47809467b48Spatrick   getExecutionDomain(const MachineInstr &MI) const override;
47909467b48Spatrick 
48009467b48Spatrick   uint16_t getExecutionDomainCustom(const MachineInstr &MI) const;
48109467b48Spatrick 
48209467b48Spatrick   void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override;
48309467b48Spatrick 
48409467b48Spatrick   bool setExecutionDomainCustom(MachineInstr &MI, unsigned Domain) const;
48509467b48Spatrick 
48609467b48Spatrick   unsigned
48709467b48Spatrick   getPartialRegUpdateClearance(const MachineInstr &MI, unsigned OpNum,
48809467b48Spatrick                                const TargetRegisterInfo *TRI) const override;
48973471bf0Spatrick   unsigned getUndefRegClearance(const MachineInstr &MI, unsigned OpNum,
49009467b48Spatrick                                 const TargetRegisterInfo *TRI) const override;
49109467b48Spatrick   void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum,
49209467b48Spatrick                                  const TargetRegisterInfo *TRI) const override;
49309467b48Spatrick 
49409467b48Spatrick   MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
49509467b48Spatrick                                       unsigned OpNum,
49609467b48Spatrick                                       ArrayRef<MachineOperand> MOs,
49709467b48Spatrick                                       MachineBasicBlock::iterator InsertPt,
498097a140dSpatrick                                       unsigned Size, Align Alignment,
49909467b48Spatrick                                       bool AllowCommute) const;
50009467b48Spatrick 
50109467b48Spatrick   bool isHighLatencyDef(int opc) const override;
50209467b48Spatrick 
50309467b48Spatrick   bool hasHighOperandLatency(const TargetSchedModel &SchedModel,
50409467b48Spatrick                              const MachineRegisterInfo *MRI,
50509467b48Spatrick                              const MachineInstr &DefMI, unsigned DefIdx,
50609467b48Spatrick                              const MachineInstr &UseMI,
50709467b48Spatrick                              unsigned UseIdx) const override;
50809467b48Spatrick 
useMachineCombiner()50909467b48Spatrick   bool useMachineCombiner() const override { return true; }
51009467b48Spatrick 
511*d415bd75Srobert   bool isAssociativeAndCommutative(const MachineInstr &Inst,
512*d415bd75Srobert                                    bool Invert) const override;
51309467b48Spatrick 
51409467b48Spatrick   bool hasReassociableOperands(const MachineInstr &Inst,
51509467b48Spatrick                                const MachineBasicBlock *MBB) const override;
51609467b48Spatrick 
51709467b48Spatrick   void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2,
51809467b48Spatrick                              MachineInstr &NewMI1,
51909467b48Spatrick                              MachineInstr &NewMI2) const override;
52009467b48Spatrick 
52109467b48Spatrick   /// analyzeCompare - For a comparison instruction, return the source registers
52209467b48Spatrick   /// in SrcReg and SrcReg2 if having two register operands, and the value it
52309467b48Spatrick   /// compares against in CmpValue. Return true if the comparison instruction
52409467b48Spatrick   /// can be analyzed.
525097a140dSpatrick   bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
526*d415bd75Srobert                       Register &SrcReg2, int64_t &CmpMask,
527*d415bd75Srobert                       int64_t &CmpValue) const override;
52809467b48Spatrick 
52909467b48Spatrick   /// optimizeCompareInstr - Check if there exists an earlier instruction that
53009467b48Spatrick   /// operates on the same source operands and sets flags in the same way as
53109467b48Spatrick   /// Compare; remove Compare if possible.
532097a140dSpatrick   bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
533*d415bd75Srobert                             Register SrcReg2, int64_t CmpMask, int64_t CmpValue,
53409467b48Spatrick                             const MachineRegisterInfo *MRI) const override;
53509467b48Spatrick 
53609467b48Spatrick   /// optimizeLoadInstr - Try to remove the load by folding it to a register
53709467b48Spatrick   /// operand at the use. We fold the load instructions if and only if the
53809467b48Spatrick   /// def and use are in the same BB. We only look at one load and see
53909467b48Spatrick   /// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register
54009467b48Spatrick   /// defined by the load we are trying to fold. DefMI returns the machine
54109467b48Spatrick   /// instruction that defines FoldAsLoadDefReg, and the function returns
54209467b48Spatrick   /// the machine instruction generated due to folding.
54309467b48Spatrick   MachineInstr *optimizeLoadInstr(MachineInstr &MI,
54409467b48Spatrick                                   const MachineRegisterInfo *MRI,
54573471bf0Spatrick                                   Register &FoldAsLoadDefReg,
54609467b48Spatrick                                   MachineInstr *&DefMI) const override;
54709467b48Spatrick 
54809467b48Spatrick   std::pair<unsigned, unsigned>
54909467b48Spatrick   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
55009467b48Spatrick 
55109467b48Spatrick   ArrayRef<std::pair<unsigned, const char *>>
55209467b48Spatrick   getSerializableDirectMachineOperandTargetFlags() const override;
55309467b48Spatrick 
554*d415bd75Srobert   outliner::OutlinedFunction getOutliningCandidateInfo(
55509467b48Spatrick       std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
55609467b48Spatrick 
55709467b48Spatrick   bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
55809467b48Spatrick                                    bool OutlineFromLinkOnceODRs) const override;
55909467b48Spatrick 
56009467b48Spatrick   outliner::InstrType
56109467b48Spatrick   getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const override;
56209467b48Spatrick 
56309467b48Spatrick   void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
56409467b48Spatrick                           const outliner::OutlinedFunction &OF) const override;
56509467b48Spatrick 
56609467b48Spatrick   MachineBasicBlock::iterator
56709467b48Spatrick   insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
56809467b48Spatrick                      MachineBasicBlock::iterator &It, MachineFunction &MF,
569*d415bd75Srobert                      outliner::Candidate &C) const override;
57009467b48Spatrick 
571*d415bd75Srobert   bool verifyInstruction(const MachineInstr &MI,
572*d415bd75Srobert                          StringRef &ErrInfo) const override;
57309467b48Spatrick #define GET_INSTRINFO_HELPER_DECLS
57409467b48Spatrick #include "X86GenInstrInfo.inc"
57509467b48Spatrick 
hasLockPrefix(const MachineInstr & MI)57609467b48Spatrick   static bool hasLockPrefix(const MachineInstr &MI) {
57709467b48Spatrick     return MI.getDesc().TSFlags & X86II::LOCK;
57809467b48Spatrick   }
57909467b48Spatrick 
580*d415bd75Srobert   std::optional<ParamLoadedValue>
581*d415bd75Srobert   describeLoadedValue(const MachineInstr &MI, Register Reg) const override;
58209467b48Spatrick 
58309467b48Spatrick protected:
58409467b48Spatrick   /// Commutes the operands in the given instruction by changing the operands
58509467b48Spatrick   /// order and/or changing the instruction's opcode and/or the immediate value
58609467b48Spatrick   /// operand.
58709467b48Spatrick   ///
58809467b48Spatrick   /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands
58909467b48Spatrick   /// to be commuted.
59009467b48Spatrick   ///
59109467b48Spatrick   /// Do not call this method for a non-commutable instruction or
59209467b48Spatrick   /// non-commutable operands.
59309467b48Spatrick   /// Even though the instruction is commutable, the method may still
59409467b48Spatrick   /// fail to commute the operands, null pointer is returned in such cases.
59509467b48Spatrick   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
59609467b48Spatrick                                        unsigned CommuteOpIdx1,
59709467b48Spatrick                                        unsigned CommuteOpIdx2) const override;
59809467b48Spatrick 
59909467b48Spatrick   /// If the specific machine instruction is a instruction that moves/copies
60009467b48Spatrick   /// value from one register to another register return destination and source
60109467b48Spatrick   /// registers as machine operands.
602*d415bd75Srobert   std::optional<DestSourcePair>
60309467b48Spatrick   isCopyInstrImpl(const MachineInstr &MI) const override;
60409467b48Spatrick 
60509467b48Spatrick private:
60609467b48Spatrick   /// This is a helper for convertToThreeAddress for 8 and 16-bit instructions.
60709467b48Spatrick   /// We use 32-bit LEA to form 3-address code by promoting to a 32-bit
60809467b48Spatrick   /// super-register and then truncating back down to a 8/16-bit sub-register.
609*d415bd75Srobert   MachineInstr *convertToThreeAddressWithLEA(unsigned MIOpc, MachineInstr &MI,
61009467b48Spatrick                                              LiveVariables *LV,
611*d415bd75Srobert                                              LiveIntervals *LIS,
61209467b48Spatrick                                              bool Is8BitOp) const;
61309467b48Spatrick 
61409467b48Spatrick   /// Handles memory folding for special case instructions, for instance those
61509467b48Spatrick   /// requiring custom manipulation of the address.
61609467b48Spatrick   MachineInstr *foldMemoryOperandCustom(MachineFunction &MF, MachineInstr &MI,
61709467b48Spatrick                                         unsigned OpNum,
61809467b48Spatrick                                         ArrayRef<MachineOperand> MOs,
61909467b48Spatrick                                         MachineBasicBlock::iterator InsertPt,
620097a140dSpatrick                                         unsigned Size, Align Alignment) const;
62109467b48Spatrick 
62209467b48Spatrick   /// isFrameOperand - Return true and the FrameIndex if the specified
62309467b48Spatrick   /// operand and follow operands form a reference to the stack frame.
62409467b48Spatrick   bool isFrameOperand(const MachineInstr &MI, unsigned int Op,
62509467b48Spatrick                       int &FrameIndex) const;
62609467b48Spatrick 
62709467b48Spatrick   /// Returns true iff the routine could find two commutable operands in the
62809467b48Spatrick   /// given machine instruction with 3 vector inputs.
62909467b48Spatrick   /// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. Their
63009467b48Spatrick   /// input values can be re-defined in this method only if the input values
63109467b48Spatrick   /// are not pre-defined, which is designated by the special value
63209467b48Spatrick   /// 'CommuteAnyOperandIndex' assigned to it.
63309467b48Spatrick   /// If both of indices are pre-defined and refer to some operands, then the
63409467b48Spatrick   /// method simply returns true if the corresponding operands are commutable
63509467b48Spatrick   /// and returns false otherwise.
63609467b48Spatrick   ///
63709467b48Spatrick   /// For example, calling this method this way:
63809467b48Spatrick   ///     unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex;
63909467b48Spatrick   ///     findThreeSrcCommutedOpIndices(MI, Op1, Op2);
64009467b48Spatrick   /// can be interpreted as a query asking to find an operand that would be
64109467b48Spatrick   /// commutable with the operand#1.
64209467b48Spatrick   ///
64309467b48Spatrick   /// If IsIntrinsic is set, operand 1 will be ignored for commuting.
64409467b48Spatrick   bool findThreeSrcCommutedOpIndices(const MachineInstr &MI,
64509467b48Spatrick                                      unsigned &SrcOpIdx1,
64609467b48Spatrick                                      unsigned &SrcOpIdx2,
64709467b48Spatrick                                      bool IsIntrinsic = false) const;
648*d415bd75Srobert 
649*d415bd75Srobert   /// Returns true when instruction \p FlagI produces the same flags as \p OI.
650*d415bd75Srobert   /// The caller should pass in the results of calling analyzeCompare on \p OI:
651*d415bd75Srobert   /// \p SrcReg, \p SrcReg2, \p ImmMask, \p ImmValue.
652*d415bd75Srobert   /// If the flags match \p OI as if it had the input operands swapped then the
653*d415bd75Srobert   /// function succeeds and sets \p IsSwapped to true.
654*d415bd75Srobert   ///
655*d415bd75Srobert   /// Examples of OI, FlagI pairs returning true:
656*d415bd75Srobert   ///   CMP %1, 42   and  CMP %1, 42
657*d415bd75Srobert   ///   CMP %1, %2   and  %3 = SUB %1, %2
658*d415bd75Srobert   ///   TEST %1, %1  and  %2 = SUB %1, 0
659*d415bd75Srobert   ///   CMP %1, %2   and  %3 = SUB %2, %1  ; IsSwapped=true
660*d415bd75Srobert   bool isRedundantFlagInstr(const MachineInstr &FlagI, Register SrcReg,
661*d415bd75Srobert                             Register SrcReg2, int64_t ImmMask, int64_t ImmValue,
662*d415bd75Srobert                             const MachineInstr &OI, bool *IsSwapped,
663*d415bd75Srobert                             int64_t *ImmDelta) const;
66409467b48Spatrick };
66509467b48Spatrick 
66609467b48Spatrick } // namespace llvm
66709467b48Spatrick 
66809467b48Spatrick #endif
669