#include "ARM.h"
#include "ARMBaseInstrInfo.h"
#include "ARMTargetMachine.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "Utils/ARMBaseInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsARM.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetOptions.h"
#include <optional>
usingnamespacellvm;
#define DEBUG_TYPE …
#define PASS_NAME …
static cl::opt<bool>
DisableShifterOp("disable-shifter-op", cl::Hidden,
cl::desc("Disable isel of shifter-op"),
cl::init(false));
namespace {
class ARMDAGToDAGISel : public SelectionDAGISel { … };
class ARMDAGToDAGISelLegacy : public SelectionDAGISelLegacy { … };
}
char ARMDAGToDAGISelLegacy::ID = …;
INITIALIZE_PASS(…)
static bool isInt32Immediate(SDNode *N, unsigned &Imm) { … }
static bool isInt32Immediate(SDValue N, unsigned &Imm) { … }
static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { … }
static bool isScaledConstantInRange(SDValue Node, int Scale,
int RangeMin, int RangeMax,
int &ScaledConstant) { … }
void ARMDAGToDAGISel::PreprocessISelDAG() { … }
bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { … }
bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
ARM_AM::ShiftOpc ShOpcVal,
unsigned ShAmt) { … }
bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N,
unsigned MaxShift,
unsigned &PowerOfTwo,
SDValue &NewMulConst) const { … }
void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) { … }
bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
SDValue &BaseReg,
SDValue &Opc,
bool CheckProfitability) { … }
bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
SDValue &BaseReg,
SDValue &ShReg,
SDValue &Opc,
bool CheckProfitability) { … }
bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out) { … }
bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
SDValue &Base,
SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
SDValue &Opc) { … }
bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc) { … }
bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc) { … }
bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc) { … }
bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { … }
bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
SDValue &Base, SDValue &Offset,
SDValue &Opc) { … }
bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc) { … }
bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset,
bool FP16) { … }
bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
SDValue &Base, SDValue &Offset) { … }
bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N,
SDValue &Base, SDValue &Offset) { … }
bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
SDValue &Align) { … }
bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
SDValue &Offset) { … }
bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
SDValue &Offset, SDValue &Label) { … }
static bool shouldUseZeroOffsetLdSt(SDValue N) { … }
bool ARMDAGToDAGISel::SelectThumbAddrModeRRSext(SDValue N, SDValue &Base,
SDValue &Offset) { … }
bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, SDValue &Base,
SDValue &Offset) { … }
bool
ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
SDValue &Base, SDValue &OffImm) { … }
bool
ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
bool
ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
bool
ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
SDValue &Base, SDValue &OffImm) { … }
template <unsigned Shift>
bool ARMDAGToDAGISel::SelectTAddrModeImm7(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
SDValue &Base, SDValue &OffImm) { … }
template <unsigned Shift>
bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
SDValue &Base, SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
SDValue &OffImm){ … }
template <unsigned Shift>
bool ARMDAGToDAGISel::SelectT2AddrModeImm7(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
template <unsigned Shift>
bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N,
SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N,
SDValue &OffImm,
unsigned Shift) { … }
template <int Min, int Max>
bool ARMDAGToDAGISel::SelectImmediateInRange(SDValue N, SDValue &OffImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N,
SDValue &Base,
SDValue &OffReg, SDValue &ShImm) { … }
bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base,
SDValue &OffImm) { … }
static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) { … }
void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) { … }
bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) { … }
bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) { … }
bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) { … }
bool ARMDAGToDAGISel::tryMVEIndexedLoad(SDNode *N) { … }
SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) { … }
SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) { … }
SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) { … }
SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) { … }
SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1,
SDValue V2, SDValue V3) { … }
SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1,
SDValue V2, SDValue V3) { … }
SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1,
SDValue V2, SDValue V3) { … }
SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl,
unsigned NumVecs, bool is64BitVector) { … }
static bool isVLDfixed(unsigned Opc)
{ … }
static bool isVSTfixed(unsigned Opc)
{ … }
static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) { … }
static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) { … }
void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs,
const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
const uint16_t *QOpcodes1) { … }
void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs,
const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
const uint16_t *QOpcodes1) { … }
void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating,
unsigned NumVecs,
const uint16_t *DOpcodes,
const uint16_t *QOpcodes) { … }
template <typename SDValueVector>
void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc,
SDValue PredicateMask) { … }
template <typename SDValueVector>
void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc,
SDValue PredicateMask,
SDValue Inactive) { … }
template <typename SDValueVector>
void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc) { … }
template <typename SDValueVector>
void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc,
EVT InactiveTy) { … }
void ARMDAGToDAGISel::SelectMVE_WB(SDNode *N, const uint16_t *Opcodes,
bool Predicated) { … }
void ARMDAGToDAGISel::SelectMVE_LongShift(SDNode *N, uint16_t Opcode,
bool Immediate,
bool HasSaturationOperand) { … }
void ARMDAGToDAGISel::SelectMVE_VADCSBC(SDNode *N, uint16_t OpcodeWithCarry,
uint16_t OpcodeWithNoCarry,
bool Add, bool Predicated) { … }
void ARMDAGToDAGISel::SelectMVE_VSHLC(SDNode *N, bool Predicated) { … }
static bool SDValueToConstBool(SDValue SDVal) { … }
void ARMDAGToDAGISel::SelectBaseMVE_VMLLDAV(SDNode *N, bool Predicated,
const uint16_t *OpcodesS,
const uint16_t *OpcodesU,
size_t Stride, size_t TySize) { … }
void ARMDAGToDAGISel::SelectMVE_VMLLDAV(SDNode *N, bool Predicated,
const uint16_t *OpcodesS,
const uint16_t *OpcodesU) { … }
void ARMDAGToDAGISel::SelectMVE_VRMLLDAVH(SDNode *N, bool Predicated,
const uint16_t *OpcodesS,
const uint16_t *OpcodesU) { … }
void ARMDAGToDAGISel::SelectMVE_VLD(SDNode *N, unsigned NumVecs,
const uint16_t *const *Opcodes,
bool HasWriteback) { … }
void ARMDAGToDAGISel::SelectMVE_VxDUP(SDNode *N, const uint16_t *Opcodes,
bool Wrapping, bool Predicated) { … }
void ARMDAGToDAGISel::SelectCDE_CXxD(SDNode *N, uint16_t Opcode,
size_t NumExtraOps, bool HasAccum) { … }
void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool IsIntrinsic,
bool isUpdating, unsigned NumVecs,
const uint16_t *DOpcodes,
const uint16_t *QOpcodes0,
const uint16_t *QOpcodes1) { … }
bool ARMDAGToDAGISel::tryInsertVectorElt(SDNode *N) { … }
bool ARMDAGToDAGISel::transformFixedFloatingPointConversion(SDNode *N,
SDNode *FMul,
bool IsUnsigned,
bool FixedToFloat) { … }
bool ARMDAGToDAGISel::tryFP_TO_INT(SDNode *N, SDLoc dl) { … }
bool ARMDAGToDAGISel::tryFMULFixed(SDNode *N, SDLoc dl) { … }
bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) { … }
bool ARMDAGToDAGISel::tryABSOp(SDNode *N){ … }
void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) { … }
static std::optional<std::pair<unsigned, unsigned>>
getContiguousRangeOfSetBits(const APInt &A) { … }
void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) { … }
static unsigned getVectorShuffleOpcode(EVT VT, unsigned Opc64[3],
unsigned Opc128[3]) { … }
void ARMDAGToDAGISel::Select(SDNode *N) { … }
static void getIntOperandsFromRegisterString(StringRef RegString,
SelectionDAG *CurDAG,
const SDLoc &DL,
std::vector<SDValue> &Ops) { … }
static inline int getBankedRegisterMask(StringRef RegString) { … }
static inline int getMClassFlagsMask(StringRef Flags) { … }
static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) { … }
static int getARClassRegisterMask(StringRef Reg, StringRef Flags) { … }
bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){ … }
bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){ … }
bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){ … }
bool ARMDAGToDAGISel::SelectInlineAsmMemoryOperand(
const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
std::vector<SDValue> &OutOps) { … }
FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM,
CodeGenOptLevel OptLevel) { … }