30#include "llvm/IR/IntrinsicsMips.h"
38#define DEBUG_TYPE "mips-isel"
47void MipsSEDAGToDAGISel::getAnalysisUsage(
AnalysisUsage &AU)
const {
52void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(
bool IsDef,
MachineInstr &
MI,
55 unsigned Mask =
MI.getOperand(1).getImm();
60 MIB.addReg(Mips::DSPPos, Flag);
63 MIB.addReg(Mips::DSPSCount, Flag);
66 MIB.addReg(Mips::DSPCarry, Flag);
69 MIB.addReg(Mips::DSPOutFlag, Flag);
72 MIB.addReg(Mips::DSPCCond, Flag);
75 MIB.addReg(Mips::DSPEFI, Flag);
78unsigned MipsSEDAGToDAGISel::getMSACtrlReg(
const SDValue RegIdx)
const {
79 uint64_t RegNum = cast<ConstantSDNode>(RegIdx)->getZExtValue();
80 return Mips::MSACtrlRegClass.getRegister(RegNum);
85 unsigned DstReg = 0, ZeroReg = 0;
88 if ((
MI.getOpcode() == Mips::ADDiu) &&
89 (
MI.getOperand(1).getReg() == Mips::ZERO) &&
90 (
MI.getOperand(2).isImm()) &&
91 (
MI.getOperand(2).getImm() == 0)) {
92 DstReg =
MI.getOperand(0).getReg();
94 }
else if ((
MI.getOpcode() == Mips::DADDiu) &&
95 (
MI.getOperand(1).getReg() == Mips::ZERO_64) &&
96 (
MI.getOperand(2).isImm()) &&
97 (
MI.getOperand(2).getImm() == 0)) {
98 DstReg =
MI.getOperand(0).getReg();
99 ZeroReg = Mips::ZERO_64;
107 E =
MRI->use_end(); U !=
E;) {
109 unsigned OpNo =
U.getOperandNo();
114 if (
MI->isPHI() ||
MI->isRegTiedToDefOperand(OpNo) ||
MI->isPseudo())
119 if (!
MRI->getRegClass(MO.
getReg())->contains(ZeroReg))
155void MipsSEDAGToDAGISel::processFunctionAfterISel(
MachineFunction &MF) {
160 for (
auto &
MBB:
MF) {
161 for (
auto &
MI:
MBB) {
162 switch (
MI.getOpcode()) {
164 addDSPCtrlRegOperands(
false,
MI,
MF);
167 addDSPCtrlRegOperands(
true,
MI,
MF);
169 case Mips::BuildPairF64_64:
170 case Mips::ExtractElementF64_64:
176 case Mips::BuildPairF64:
177 case Mips::ExtractElementF64:
183 if (
MI.getOperand(0).isGlobal() &&
184 MI.getOperand(0).getGlobal()->getGlobalIdentifier() ==
"_mcount")
187 case Mips::JALRPseudo:
188 case Mips::JALR64Pseudo:
189 case Mips::JALR16_MM:
190 if (
MI.getOperand(2).isMCSymbol() &&
191 MI.getOperand(2).getMCSymbol()->getName() ==
"_mcount")
195 if (
MI.getOperand(3).isMCSymbol() &&
196 MI.getOperand(3).getMCSymbol()->getName() ==
"_mcount")
200 replaceUsesWithZeroReg(
MRI,
MI);
210 EVT VT =
LHS.getValueType();
239 MVT::Glue, CstOne, InGlue);
242 Mips::EXT,
DL, MVT::i32,
SDValue(DSPCtrlField, 0), OuFlag, CstOne);
261 SDValue(DSPCtrlFinal, 0), CstOne);
271 EVT ValTy =
Addr.getValueType();
281bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset(
283 unsigned ShiftAmount = 0)
const {
285 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
286 if (
isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) {
287 EVT ValTy =
Addr.getValueType();
291 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
297 const Align Alignment(1ULL << ShiftAmount);
298 if (!
isAligned(Alignment, CN->getZExtValue()))
348 if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
349 isa<JumpTableSDNode>(Opnd0)) {
442 if (isa<FrameIndexSDNode>(
Base))
446 unsigned CnstOff = CN->getZExtValue();
447 return (CnstOff == (CnstOff & 0x3c));
511bool MipsSEDAGToDAGISel::selectVSplat(
SDNode *
N,
APInt &Imm,
512 unsigned MinSizeInBits)
const {
521 APInt SplatValue, SplatUndef;
522 unsigned SplatBitSize;
525 if (!
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
550bool MipsSEDAGToDAGISel::
552 unsigned ImmBitSize)
const {
554 EVT EltTy =
N->getValueType(0).getVectorElementType();
557 N =
N->getOperand(0);
573bool MipsSEDAGToDAGISel::
575 return selectVSplatCommon(
N, Imm,
false, 1);
578bool MipsSEDAGToDAGISel::
580 return selectVSplatCommon(
N, Imm,
false, 2);
583bool MipsSEDAGToDAGISel::
585 return selectVSplatCommon(
N, Imm,
false, 3);
589bool MipsSEDAGToDAGISel::
591 return selectVSplatCommon(
N, Imm,
false, 4);
595bool MipsSEDAGToDAGISel::
597 return selectVSplatCommon(
N, Imm,
false, 5);
601bool MipsSEDAGToDAGISel::
603 return selectVSplatCommon(
N, Imm,
false, 6);
607bool MipsSEDAGToDAGISel::
609 return selectVSplatCommon(
N, Imm,
false, 8);
613bool MipsSEDAGToDAGISel::
615 return selectVSplatCommon(
N, Imm,
true, 5);
628bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(
SDValue N,
SDValue &Imm)
const {
630 EVT EltTy =
N->getValueType(0).getVectorElementType();
633 N =
N->getOperand(0);
659bool MipsSEDAGToDAGISel::selectVSplatMaskL(
SDValue N,
SDValue &Imm)
const {
661 EVT EltTy =
N->getValueType(0).getVectorElementType();
664 N =
N->getOperand(0);
671 if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) {
692bool MipsSEDAGToDAGISel::selectVSplatMaskR(
SDValue N,
SDValue &Imm)
const {
694 EVT EltTy =
N->getValueType(0).getVectorElementType();
697 N =
N->getOperand(0);
703 if (ImmValue == (ImmValue & ~(ImmValue + 1))) {
712bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(
SDValue N,
715 EVT EltTy =
N->getValueType(0).getVectorElementType();
718 N =
N->getOperand(0);
722 int32_t
Log2 = (~ImmValue).exactLogBase2();
733bool MipsSEDAGToDAGISel::trySelect(
SDNode *
Node) {
734 unsigned Opcode =
Node->getOpcode();
744 case Mips::PseudoD_SELECT_I:
745 case Mips::PseudoD_SELECT_I64: {
754 EVT NodeTys[] = {VT, VT};
756 ? Mips::PseudoD_SELECT_I64
757 : Mips::PseudoD_SELECT_I,
768 auto *CN = cast<ConstantFPSDNode>(
Node);
769 if (
Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
772 Mips::ZERO_64, MVT::i64);
777 Mips::ZERO, MVT::i32);
779 MVT::f64, Zero, Zero));
782 Mips::ZERO, MVT::i32);
784 MVT::f64, Zero, Zero));
792 auto *CN = cast<ConstantSDNode>(
Node);
793 int64_t
Imm = CN->getSExtValue();
794 unsigned Size = CN->getValueSizeInBits(0);
813 if (Inst->Opc == Mips::LUi64)
822 for (++Inst; Inst != Seq.
end(); ++Inst) {
834 const unsigned IntrinsicOpcode =
835 cast<ConstantSDNode>(
Node->getOperand(1))->getZExtValue();
836 switch (IntrinsicOpcode) {
840 case Intrinsic::mips_cfcmsa: {
844 getMSACtrlReg(RegIdx), MVT::i32);
848 case Intrinsic::mips_ldr_d:
849 case Intrinsic::mips_ldr_w: {
850 unsigned Op = (IntrinsicOpcode == Intrinsic::mips_ldr_d) ? Mips::LDR_D
854 assert(
Node->getNumOperands() == 4 &&
"Unexpected number of operands.");
864 "Invalid instruction operand.");
868 cast<ConstantSDNode>(
Constant)->getConstantIntValue();
875 assert(
Node->getValueType(0).is128BitVector());
888 switch (cast<ConstantSDNode>(
Node->getOperand(0))->getZExtValue()) {
892 case Intrinsic::mips_move_v:
896 Node->getValueType(0),
897 Node->getOperand(1)));
904 const unsigned IntrinsicOpcode =
905 cast<ConstantSDNode>(
Node->getOperand(1))->getZExtValue();
906 switch (IntrinsicOpcode) {
910 case Intrinsic::mips_ctcmsa: {
915 getMSACtrlReg(RegIdx),
Value);
919 case Intrinsic::mips_str_d:
920 case Intrinsic::mips_str_w: {
921 unsigned Op = (IntrinsicOpcode == Intrinsic::mips_str_d) ? Mips::STR_D
925 assert(
Node->getNumOperands() == 5 &&
"Unexpected number of operands.");
936 "Invalid instruction operand.");
940 cast<ConstantSDNode>(
Constant)->getConstantIntValue();
958 MVT ResTy =
Node->getSimpleValueType(0);
959 assert((ResTy == MVT::f64 || ResTy == MVT::f32) &&
960 "Unsupported float type!");
962 if (ResTy == MVT::f64)
970 Opc = Mips::FABS_D64_MM;
973 Opc = Mips::FABS_D32_MM;
976 Opc = Mips::FABS_S_MM;
998 if (
Node->getValueType(0) != MVT::i32 &&
Node->getValueType(0) != MVT::i64)
1001 if (
Node->getNumOperands() != 4)
1008 MVT ResTy =
Node->getSimpleValueType(0);
1016 if (Pos +
Size > 64)
1019 if (ResTy != MVT::i32 && ResTy != MVT::i64)
1022 unsigned Opcode = 0;
1023 if (ResTy == MVT::i32) {
1024 if (Pos +
Size <= 32)
1027 if (Pos +
Size <= 32)
1028 Opcode = Mips::DINS;
1029 else if (Pos < 32 && 1 <
Size)
1030 Opcode = Mips::DINSM;
1032 Opcode = Mips::DINSU;
1049 unsigned RdhwrOpc, DestReg;
1051 if (PtrVT == MVT::i32) {
1052 RdhwrOpc = Mips::RDHWR;
1055 RdhwrOpc = Mips::RDHWR64;
1056 DestReg = Mips::V1_64;
1088 APInt SplatValue, SplatUndef;
1089 unsigned SplatBitSize;
1103 switch (SplatBitSize) {
1107 LdiOp = Mips::LDI_B;
1108 ViaVecTy = MVT::v16i8;
1111 LdiOp = Mips::LDI_H;
1112 ViaVecTy = MVT::v8i16;
1115 LdiOp = Mips::LDI_W;
1116 ViaVecTy = MVT::v4i32;
1119 LdiOp = Mips::LDI_D;
1120 ViaVecTy = MVT::v2i64;
1136 ((
ABI.IsO32() && SplatBitSize < 64) ||
1137 (
ABI.IsN32() ||
ABI.IsN64()))) {
1143 bool Is32BitSplat =
ABI.IsO32() || SplatBitSize < 64;
1144 const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu;
1145 const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64;
1147 Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT);
1149 const unsigned FILLOp =
1152 : (SplatBitSize == 32 ? Mips::FILL_W
1153 : (SplatBitSize == 64 ? Mips::FILL_D : 0));
1155 assert(FILLOp != 0 &&
"Unknown FILL Op for splat synthesis!");
1156 assert((!
ABI.IsO32() || (FILLOp != Mips::FILL_D)) &&
1157 "Attempting to use fill.d on MIPS32!");
1165 }
else if (SplatValue.
isSignedIntN(32) && SplatBitSize == 32) {
1182 assert((
Hi ||
Lo) &&
"Zero case reached 32 bit case splat synthesis!");
1186 }
else if (SplatValue.
isSignedIntN(32) && SplatBitSize == 64 &&
1187 (
ABI.IsN32() ||
ABI.IsN64())) {
1206 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1280 Highest ?
SDValue(HiRes, 0) : ZeroVal,
1289 Mips::INSERT_W,
DL, MVT::v4i32,
SDValue(Res, 0),
1290 (Highest || Higher) ?
SDValue(HiRes, 0) : ZeroVal,
1298 Mips::COPY_TO_REGCLASS,
DL, ViaVecTy,
SDValue(Res, 0),
1302 Mips::SPLATI_D,
DL, MVT::v2i64,
SDValue(Res, 0),
1304 }
else if (
ABI.IsN64() ||
ABI.IsN32()) {
1308 const bool ResNonZero =
Hi ||
Lo;
1312 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1319 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1341 }
else if (HiResNonZero) {
1343 Mips::DSLL32,
DL, MVT::i64,
SDValue(HiRes, 0),
1347 "Zero splat value handled by non-zero 64bit splat synthesis!");
1357 if (ResVecTy != ViaVecTy) {
1380bool MipsSEDAGToDAGISel::SelectInlineAsmMemoryOperand(
1382 std::vector<SDValue> &OutOps) {
1385 switch(ConstraintID) {
1392 OutOps.push_back(
Base);
1393 OutOps.push_back(
Offset);
1396 OutOps.push_back(
Op);
1406 OutOps.push_back(
Base);
1407 OutOps.push_back(
Offset);
1410 OutOps.push_back(
Op);
1419 OutOps.push_back(
Base);
1420 OutOps.push_back(
Offset);
1426 OutOps.push_back(
Base);
1427 OutOps.push_back(
Offset);
1432 OutOps.push_back(
Base);
1433 OutOps.push_back(
Offset);
1437 OutOps.push_back(
Op);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
mir Rename Register Operands
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
unsigned getBitWidth() const
Return the number of bits in the APInt.
int32_t exactLogBase2() const
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
Legacy analysis pass which computes a DominatorTree.
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Class to represent integer types.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const MipsSubtarget * Subtarget
Keep a pointer to the MipsSubtarget around so that we can make the right decision when generating cod...
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
bool inMicroMipsMode() const
bool inMips16Mode() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
unsigned getOpcode() const
const TargetLowering * TLI
const TargetInstrInfo * TII
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetLowering * getTargetLowering() const
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
const DataLayout & getDataLayout() const
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool isPositionIndependent() const
unsigned getID() const
Return the register class ID number.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ ADD
Simple integer binary arithmetic operators.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
FunctionPass * createMipsSEISelDag(MipsTargetMachine &TM, CodeGenOptLevel OptLevel)
CodeGenOptLevel
Code generation optimization level.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
unsigned Log2(Align A)
Returns the log2 of the alignment.
This struct is a compact representation of a valid (non-zero power of two) alignment.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.