llvm/llvm/lib/Target/ARM/ARMBaseInstrInfo.h

//===-- ARMBaseInstrInfo.h - ARM Base Instruction Information ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the Base ARM implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H
#define LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H

#include "ARMBaseRegisterInfo.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "MCTargetDesc/ARMMCTargetDesc.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsARM.h"
#include "llvm/Support/ErrorHandling.h"
#include <array>
#include <cstdint>

#define GET_INSTRINFO_HEADER
#include "ARMGenInstrInfo.inc"

namespace llvm {

class ARMBaseRegisterInfo;
class ARMSubtarget;

class ARMBaseInstrInfo : public ARMGenInstrInfo {};

/// Get the operands corresponding to the given \p Pred value. By default, the
/// predicate register is assumed to be 0 (no register), but you can pass in a
/// \p PredReg if that is not the case.
static inline std::array<MachineOperand, 2> predOps(ARMCC::CondCodes Pred,
                                                    unsigned PredReg = 0) {}

/// Get the operand corresponding to the conditional code result. By default,
/// this is 0 (no register).
static inline MachineOperand condCodeOp(unsigned CCReg = 0) {}

/// Get the operand corresponding to the conditional code result for Thumb1.
/// This operand will always refer to CPSR and it will have the Define flag set.
/// You can optionally set the Dead flag by means of \p isDead.
static inline MachineOperand t1CondCodeOp(bool isDead = false) {}

static inline
bool isUncondBranchOpcode(int Opc) {}

// This table shows the VPT instruction variants, i.e. the different
// mask field encodings, see also B5.6. Predication/conditional execution in
// the ArmARM.
static inline bool isVPTOpcode(int Opc) {}

static inline
unsigned VCMPOpcodeToVPT(unsigned Opcode) {}

static inline
bool isCondBranchOpcode(int Opc) {}

static inline bool isJumpTableBranchOpcode(int Opc) {}

static inline
bool isIndirectBranchOpcode(int Opc) {}

static inline bool isIndirectCall(const MachineInstr &MI) {}

static inline bool isIndirectControlFlowNotComingBack(const MachineInstr &MI) {}

static inline bool isSpeculationBarrierEndBBOpcode(int Opc) {}

static inline bool isPopOpcode(int Opc) {}

static inline bool isPushOpcode(int Opc) {}

static inline bool isSubImmOpcode(int Opc) {}

static inline bool isMovRegOpcode(int Opc) {}
/// isValidCoprocessorNumber - decide whether an explicit coprocessor
/// number is legal in generic instructions like CDP. The answer can
/// vary with the subtarget.
static inline bool isValidCoprocessorNumber(unsigned Num,
                                            const FeatureBitset& featureBits) {}

static inline bool isSEHInstruction(const MachineInstr &MI) {}

/// getInstrPredicate - If instruction is predicated, returns its predicate
/// condition, otherwise returns AL. It also returns the condition code
/// register by reference.
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg);

unsigned getMatchingCondBranchOpcode(unsigned Opc);

/// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether
/// the instruction is encoded with an 'S' bit is determined by the optional
/// CPSR def operand.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc);

/// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of
/// instructions to materializea destreg = basereg + immediate in ARM / Thumb2
/// code.
void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator &MBBI,
                             const DebugLoc &dl, Register DestReg,
                             Register BaseReg, int NumBytes,
                             ARMCC::CondCodes Pred, Register PredReg,
                             const ARMBaseInstrInfo &TII, unsigned MIFlags = 0);

void emitT2RegPlusImmediate(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator &MBBI,
                            const DebugLoc &dl, Register DestReg,
                            Register BaseReg, int NumBytes,
                            ARMCC::CondCodes Pred, Register PredReg,
                            const ARMBaseInstrInfo &TII, unsigned MIFlags = 0);
void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator &MBBI,
                               const DebugLoc &dl, Register DestReg,
                               Register BaseReg, int NumBytes,
                               const TargetInstrInfo &TII,
                               const ARMBaseRegisterInfo &MRI,
                               unsigned MIFlags = 0);

/// Tries to add registers to the reglist of a given base-updating
/// push/pop instruction to adjust the stack by an additional
/// NumBytes. This can save a few bytes per function in code-size, but
/// obviously generates more memory traffic. As such, it only takes
/// effect in functions being optimised for size.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,
                                MachineFunction &MF, MachineInstr *MI,
                                unsigned NumBytes);

/// rewriteARMFrameIndex / rewriteT2FrameIndex -
/// Rewrite MI to access 'Offset' bytes from the FP. Return false if the
/// offset could not be handled directly in MI, and return the left-over
/// portion by reference.
bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
                          Register FrameReg, int &Offset,
                          const ARMBaseInstrInfo &TII);

bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
                         Register FrameReg, int &Offset,
                         const ARMBaseInstrInfo &TII,
                         const TargetRegisterInfo *TRI);

/// Return true if Reg is defd between From and To
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From,
                            MachineBasicBlock::iterator To,
                            const TargetRegisterInfo *TRI);

/// Search backwards from a tBcc to find a tCMPi8 against 0, meaning
/// we can convert them to a tCBZ or tCBNZ. Return nullptr if not found.
MachineInstr *findCMPToFoldIntoCBZ(MachineInstr *Br,
                                   const TargetRegisterInfo *TRI);

void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB);
void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg);

void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond);
void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond,
                              unsigned Inactive);

/// Returns the number of instructions required to materialize the given
/// constant in a register, or 3 if a literal pool load is needed.
/// If ForCodesize is specified, an approximate cost in bytes is returned.
unsigned ConstantMaterializationCost(unsigned Val,
                                     const ARMSubtarget *Subtarget,
                                     bool ForCodesize = false);

/// Returns true if Val1 has a lower Constant Materialization Cost than Val2.
/// Uses the cost from ConstantMaterializationCost, first with ForCodesize as
/// specified. If the scores are equal, return the comparison for !ForCodesize.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2,
                                         const ARMSubtarget *Subtarget,
                                         bool ForCodesize = false);

// Return the immediate if this is ADDri or SUBri, scaled as appropriate.
// Returns 0 for unknown instructions.
inline int getAddSubImmediate(MachineInstr &MI) {}

// Given a memory access Opcode, check that the give Imm would be a valid Offset
// for this instruction using its addressing mode.
inline bool isLegalAddressImm(unsigned Opcode, int Imm,
                              const TargetInstrInfo *TII) {}

// Return true if the given intrinsic is a gather
inline bool isGather(IntrinsicInst *IntInst) {}

// Return true if the given intrinsic is a scatter
inline bool isScatter(IntrinsicInst *IntInst) {}

// Return true if the given intrinsic is a gather or scatter
inline bool isGatherScatter(IntrinsicInst *IntInst) {}

unsigned getBLXOpcode(const MachineFunction &MF);
unsigned gettBLXrOpcode(const MachineFunction &MF);
unsigned getBLXpredOpcode(const MachineFunction &MF);

} // end namespace llvm

#endif // LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H