mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
22f779d1fd
This patch implements the infrastructure to use named register constructs in programs that need access to specific registers (bare metal, kernels, etc). So far, only the stack pointer is supported as a technology preview, but as it is, the intrinsic can already support all non-allocatable registers from any architecture. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208104 91177308-0d34-0410-b5e6-96231b3b80d8
411 lines
15 KiB
C++
411 lines
15 KiB
C++
//==-- AArch64ISelLowering.h - AArch64 DAG Lowering Interface ----*- C++ -*-==//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the interfaces that AArch64 uses to lower LLVM code into a
|
|
// selection DAG.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_TARGET_AARCH64_ISELLOWERING_H
|
|
#define LLVM_TARGET_AARCH64_ISELLOWERING_H
|
|
|
|
#include "Utils/AArch64BaseInfo.h"
|
|
#include "llvm/CodeGen/CallingConvLower.h"
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
#include "llvm/IR/Intrinsics.h"
|
|
#include "llvm/Target/TargetLowering.h"
|
|
|
|
namespace llvm {
|
|
namespace AArch64ISD {
|
|
enum NodeType {
|
|
// Start the numbering from where ISD NodeType finishes.
|
|
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
|
|
|
// This is a conditional branch which also notes the flag needed
|
|
// (eq/sgt/...). A64 puts this information on the branches rather than
|
|
// compares as LLVM does.
|
|
BR_CC,
|
|
|
|
// A node to be selected to an actual call operation: either BL or BLR in
|
|
// the absence of tail calls.
|
|
Call,
|
|
|
|
// Indicates a floating-point immediate which fits into the format required
|
|
// by the FMOV instructions. First (and only) operand is the 8-bit encoded
|
|
// value of that immediate.
|
|
FPMOV,
|
|
|
|
// Corresponds directly to an EXTR instruction. Operands are an LHS an RHS
|
|
// and an LSB.
|
|
EXTR,
|
|
|
|
// Wraps a load from the GOT, which should always be performed with a 64-bit
|
|
// load instruction. This prevents the DAG combiner folding a truncate to
|
|
// form a smaller memory access.
|
|
GOTLoad,
|
|
|
|
// Performs a bitfield insert. Arguments are: the value being inserted into;
|
|
// the value being inserted; least significant bit changed; width of the
|
|
// field.
|
|
BFI,
|
|
|
|
// Simply a convenient node inserted during ISelLowering to represent
|
|
// procedure return. Will almost certainly be selected to "RET".
|
|
Ret,
|
|
|
|
/// Extracts a field of contiguous bits from the source and sign extends
|
|
/// them into a single register. Arguments are: source; immr; imms. Note
|
|
/// these are pre-encoded since DAG matching can't cope with combining LSB
|
|
/// and Width into these values itself.
|
|
SBFX,
|
|
|
|
/// This is an A64-ification of the standard LLVM SELECT_CC operation. The
|
|
/// main difference is that it only has the values and an A64 condition,
|
|
/// which will be produced by a setcc instruction.
|
|
SELECT_CC,
|
|
|
|
/// This serves most of the functions of the LLVM SETCC instruction, for two
|
|
/// purposes. First, it prevents optimisations from fiddling with the
|
|
/// compare after we've moved the CondCode information onto the SELECT_CC or
|
|
/// BR_CC instructions. Second, it gives a legal instruction for the actual
|
|
/// comparison.
|
|
///
|
|
/// It keeps a record of the condition flags asked for because certain
|
|
/// instructions are only valid for a subset of condition codes.
|
|
SETCC,
|
|
|
|
// Designates a node which is a tail call: both a call and a return
|
|
// instruction as far as selction is concerned. It should be selected to an
|
|
// unconditional branch. Has the usual plethora of call operands, but: 1st
|
|
// is callee, 2nd is stack adjustment required immediately before branch.
|
|
TC_RETURN,
|
|
|
|
// Designates a call used to support the TLS descriptor ABI. The call itself
|
|
// will be indirect ("BLR xN") but a relocation-specifier (".tlsdesccall
|
|
// var") must be attached somehow during code generation. It takes two
|
|
// operands: the callee and the symbol to be relocated against.
|
|
TLSDESCCALL,
|
|
|
|
// Leaf node which will be lowered to an appropriate MRS to obtain the
|
|
// thread pointer: TPIDR_EL0.
|
|
THREAD_POINTER,
|
|
|
|
/// Extracts a field of contiguous bits from the source and zero extends
|
|
/// them into a single register. Arguments are: source; immr; imms. Note
|
|
/// these are pre-encoded since DAG matching can't cope with combining LSB
|
|
/// and Width into these values itself.
|
|
UBFX,
|
|
|
|
// Wraps an address which the ISelLowering phase has decided should be
|
|
// created using the large memory model style: i.e. a sequence of four
|
|
// movz/movk instructions.
|
|
WrapperLarge,
|
|
|
|
// Wraps an address which the ISelLowering phase has decided should be
|
|
// created using the small memory model style: i.e. adrp/add or
|
|
// adrp/mem-op. This exists to prevent bare TargetAddresses which may never
|
|
// get selected.
|
|
WrapperSmall,
|
|
|
|
// Vector move immediate
|
|
NEON_MOVIMM,
|
|
|
|
// Vector Move Inverted Immediate
|
|
NEON_MVNIMM,
|
|
|
|
// Vector FP move immediate
|
|
NEON_FMOVIMM,
|
|
|
|
// Vector permute
|
|
NEON_UZP1,
|
|
NEON_UZP2,
|
|
NEON_ZIP1,
|
|
NEON_ZIP2,
|
|
NEON_TRN1,
|
|
NEON_TRN2,
|
|
|
|
// Vector Element reverse
|
|
NEON_REV64,
|
|
NEON_REV32,
|
|
NEON_REV16,
|
|
|
|
// Vector compare
|
|
NEON_CMP,
|
|
|
|
// Vector compare zero
|
|
NEON_CMPZ,
|
|
|
|
// Vector compare bitwise test
|
|
NEON_TST,
|
|
|
|
// Vector saturating shift
|
|
NEON_QSHLs,
|
|
NEON_QSHLu,
|
|
|
|
// Vector dup
|
|
NEON_VDUP,
|
|
|
|
// Vector dup by lane
|
|
NEON_VDUPLANE,
|
|
|
|
// Vector extract
|
|
NEON_VEXTRACT,
|
|
|
|
// NEON duplicate lane loads
|
|
NEON_LD2DUP = ISD::FIRST_TARGET_MEMORY_OPCODE,
|
|
NEON_LD3DUP,
|
|
NEON_LD4DUP,
|
|
|
|
// NEON loads with post-increment base updates:
|
|
NEON_LD1_UPD,
|
|
NEON_LD2_UPD,
|
|
NEON_LD3_UPD,
|
|
NEON_LD4_UPD,
|
|
NEON_LD1x2_UPD,
|
|
NEON_LD1x3_UPD,
|
|
NEON_LD1x4_UPD,
|
|
|
|
// NEON stores with post-increment base updates:
|
|
NEON_ST1_UPD,
|
|
NEON_ST2_UPD,
|
|
NEON_ST3_UPD,
|
|
NEON_ST4_UPD,
|
|
NEON_ST1x2_UPD,
|
|
NEON_ST1x3_UPD,
|
|
NEON_ST1x4_UPD,
|
|
|
|
// NEON duplicate lane loads with post-increment base updates:
|
|
NEON_LD2DUP_UPD,
|
|
NEON_LD3DUP_UPD,
|
|
NEON_LD4DUP_UPD,
|
|
|
|
// NEON lane loads with post-increment base updates:
|
|
NEON_LD2LN_UPD,
|
|
NEON_LD3LN_UPD,
|
|
NEON_LD4LN_UPD,
|
|
|
|
// NEON lane store with post-increment base updates:
|
|
NEON_ST2LN_UPD,
|
|
NEON_ST3LN_UPD,
|
|
NEON_ST4LN_UPD
|
|
};
|
|
}
|
|
|
|
|
|
class AArch64Subtarget;
|
|
class AArch64TargetMachine;
|
|
|
|
class AArch64TargetLowering : public TargetLowering {
|
|
public:
|
|
explicit AArch64TargetLowering(AArch64TargetMachine &TM);
|
|
|
|
const char *getTargetNodeName(unsigned Opcode) const override;
|
|
|
|
CCAssignFn *CCAssignFnForNode(CallingConv::ID CC) const;
|
|
|
|
SDValue LowerFormalArguments(SDValue Chain,
|
|
CallingConv::ID CallConv, bool isVarArg,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
SDLoc dl, SelectionDAG &DAG,
|
|
SmallVectorImpl<SDValue> &InVals) const override;
|
|
|
|
SDValue LowerReturn(SDValue Chain,
|
|
CallingConv::ID CallConv, bool isVarArg,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
SDLoc dl, SelectionDAG &DAG) const override;
|
|
|
|
unsigned getByValTypeAlignment(Type *Ty) const override;
|
|
|
|
SDValue LowerCall(CallLoweringInfo &CLI,
|
|
SmallVectorImpl<SDValue> &InVals) const override;
|
|
|
|
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
|
|
CallingConv::ID CallConv, bool IsVarArg,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
SDLoc dl, SelectionDAG &DAG,
|
|
SmallVectorImpl<SDValue> &InVals) const;
|
|
|
|
SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
bool isConcatVector(SDValue Op, SelectionDAG &DAG, SDValue V0, SDValue V1,
|
|
const int *Mask, SDValue &Res) const;
|
|
|
|
bool isKnownShuffleVector(SDValue Op, SelectionDAG &DAG, SDValue &V0,
|
|
SDValue &V1, int *Mask) const;
|
|
|
|
SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
|
|
const AArch64Subtarget *ST) const;
|
|
|
|
SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
void SaveVarArgRegisters(CCState &CCInfo, SelectionDAG &DAG, SDLoc DL,
|
|
SDValue &Chain) const;
|
|
|
|
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
|
|
/// for tail call optimization. Targets which want to do tail call
|
|
/// optimization should implement this function.
|
|
bool IsEligibleForTailCallOptimization(SDValue Callee,
|
|
CallingConv::ID CalleeCC,
|
|
bool IsVarArg,
|
|
bool IsCalleeStructRet,
|
|
bool IsCallerStructRet,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
SelectionDAG& DAG) const;
|
|
|
|
/// Finds the incoming stack arguments which overlap the given fixed stack
|
|
/// object and incorporates their load into the current chain. This prevents
|
|
/// an upcoming store from clobbering the stack argument before it's used.
|
|
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG,
|
|
MachineFrameInfo *MFI, int ClobberedFI) const;
|
|
|
|
EVT getSetCCResultType(LLVMContext &Context, EVT VT) const override;
|
|
|
|
bool DoesCalleeRestoreStack(CallingConv::ID CallCC, bool TailCallOpt) const;
|
|
|
|
bool IsTailCallConvention(CallingConv::ID CallCC) const;
|
|
|
|
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
|
|
|
|
bool isLegalICmpImmediate(int64_t Val) const override;
|
|
|
|
/// \brief Return true if the addressing mode represented by AM is legal for
|
|
/// this target, for a load/store of the specified type.
|
|
bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override;
|
|
|
|
/// \brief Return the cost of the scaling factor used in the addressing
|
|
/// mode represented by AM for this target, for a load/store
|
|
/// of the specified type.
|
|
/// If the AM is supported, the return value must be >= 0.
|
|
/// If the AM is not supported, it returns a negative value.
|
|
int getScalingFactorCost(const AddrMode &AM, Type *Ty) const override;
|
|
|
|
bool isTruncateFree(Type *Ty1, Type *Ty2) const override;
|
|
bool isTruncateFree(EVT VT1, EVT VT2) const override;
|
|
|
|
bool isZExtFree(Type *Ty1, Type *Ty2) const override;
|
|
bool isZExtFree(EVT VT1, EVT VT2) const override;
|
|
bool isZExtFree(SDValue Val, EVT VT2) const override;
|
|
|
|
SDValue getSelectableIntSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
|
|
SDValue &A64cc, SelectionDAG &DAG, SDLoc &dl) const;
|
|
|
|
MachineBasicBlock *
|
|
EmitInstrWithCustomInserter(MachineInstr *MI,
|
|
MachineBasicBlock *MBB) const override;
|
|
|
|
MachineBasicBlock *
|
|
emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *MBB,
|
|
unsigned Size, unsigned Opcode) const;
|
|
|
|
MachineBasicBlock *
|
|
emitAtomicBinaryMinMax(MachineInstr *MI, MachineBasicBlock *BB,
|
|
unsigned Size, unsigned CmpOp,
|
|
A64CC::CondCodes Cond) const;
|
|
MachineBasicBlock *
|
|
emitAtomicCmpSwap(MachineInstr *MI, MachineBasicBlock *BB,
|
|
unsigned Size) const;
|
|
|
|
MachineBasicBlock *
|
|
EmitF128CSEL(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
|
|
|
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerF128ToCall(SDValue Op, SelectionDAG &DAG,
|
|
RTLIB::Libcall Call) const;
|
|
SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, bool IsSigned) const;
|
|
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
SDValue LowerGlobalAddressELFSmall(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerGlobalAddressELFLarge(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
SDValue LowerTLSDescCall(SDValue SymAddr, SDValue DescAddr, SDLoc DL,
|
|
SelectionDAG &DAG) const;
|
|
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, bool IsSigned) const;
|
|
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const;
|
|
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
|
|
|
SDValue PerformDAGCombine(SDNode *N,DAGCombinerInfo &DCI) const override;
|
|
|
|
unsigned getRegisterByName(const char* RegName) const;
|
|
|
|
/// isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster
|
|
/// than a pair of fmul and fadd instructions. fmuladd intrinsics will be
|
|
/// expanded to FMAs when this method returns true, otherwise fmuladd is
|
|
/// expanded to fmul + fadd.
|
|
bool isFMAFasterThanFMulAndFAdd(EVT VT) const override;
|
|
|
|
/// allowsUnalignedMemoryAccesses - Returns true if the target allows
|
|
/// unaligned memory accesses of the specified type. Returns whether it
|
|
/// is "fast" by reference in the second argument.
|
|
bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AddrSpace,
|
|
bool *Fast) const override;
|
|
|
|
ConstraintType
|
|
getConstraintType(const std::string &Constraint) const override;
|
|
|
|
ConstraintWeight
|
|
getSingleConstraintMatchWeight(AsmOperandInfo &Info,
|
|
const char *Constraint) const override;
|
|
void LowerAsmOperandForConstraint(SDValue Op,
|
|
std::string &Constraint,
|
|
std::vector<SDValue> &Ops,
|
|
SelectionDAG &DAG) const override;
|
|
|
|
std::pair<unsigned, const TargetRegisterClass*>
|
|
getRegForInlineAsmConstraint(const std::string &Constraint,
|
|
MVT VT) const override;
|
|
|
|
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I,
|
|
unsigned Intrinsic) const override;
|
|
|
|
/// getMaximalGlobalOffset - Returns the maximal possible offset which can
|
|
/// be used for loads / stores from the global.
|
|
unsigned getMaximalGlobalOffset() const override;
|
|
|
|
protected:
|
|
std::pair<const TargetRegisterClass*, uint8_t>
|
|
findRepresentativeClass(MVT VT) const override;
|
|
|
|
private:
|
|
const InstrItineraryData *Itins;
|
|
|
|
const AArch64Subtarget *getSubtarget() const {
|
|
return &getTargetMachine().getSubtarget<AArch64Subtarget>();
|
|
}
|
|
};
|
|
enum NeonModImmType {
|
|
Neon_Mov_Imm,
|
|
Neon_Mvn_Imm
|
|
};
|
|
|
|
extern SDValue ScanBUILD_VECTOR(SDValue Op, bool &isOnlyLowElement,
|
|
bool &usesOnlyOneValue, bool &hasDominantValue,
|
|
bool &isConstant, bool &isUNDEF);
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_TARGET_AARCH64_ISELLOWERING_H
|