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