27#include "llvm/IR/IntrinsicsMips.h"
33#define DEBUG_TYPE "mips-isel"
47void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(
bool IsDef,
MachineInstr &
MI,
50 unsigned Mask =
MI.getOperand(1).getImm();
55 MIB.addReg(Mips::DSPPos, Flag);
58 MIB.addReg(Mips::DSPSCount, Flag);
61 MIB.addReg(Mips::DSPCarry, Flag);
64 MIB.addReg(Mips::DSPOutFlag, Flag);
67 MIB.addReg(Mips::DSPCCond, Flag);
70 MIB.addReg(Mips::DSPEFI, Flag);
73unsigned MipsSEDAGToDAGISel::getMSACtrlReg(
const SDValue RegIdx)
const {
75 return Mips::MSACtrlRegClass.getRegister(RegNum);
80 unsigned DstReg = 0, ZeroReg = 0;
83 if ((
MI.getOpcode() == Mips::ADDiu) &&
84 (
MI.getOperand(1).getReg() == Mips::ZERO) &&
85 (
MI.getOperand(2).isImm()) &&
86 (
MI.getOperand(2).getImm() == 0)) {
87 DstReg =
MI.getOperand(0).getReg();
89 }
else if ((
MI.getOpcode() == Mips::DADDiu) &&
90 (
MI.getOperand(1).getReg() == Mips::ZERO_64) &&
91 (
MI.getOperand(2).isImm()) &&
92 (
MI.getOperand(2).getImm() == 0)) {
93 DstReg =
MI.getOperand(0).getReg();
94 ZeroReg = Mips::ZERO_64;
102 E =
MRI->use_end(); U != E;) {
104 unsigned OpNo =
U.getOperandNo();
109 if (
MI->isPHI() ||
MI->isRegTiedToDefOperand(OpNo) ||
MI->isPseudo())
114 if (!
MRI->getRegClass(MO.
getReg())->contains(ZeroReg))
150void MipsSEDAGToDAGISel::processFunctionAfterISel(
MachineFunction &MF) {
155 for (
auto &
MBB:
MF) {
156 for (
auto &
MI:
MBB) {
157 switch (
MI.getOpcode()) {
159 addDSPCtrlRegOperands(
false,
MI,
MF);
162 addDSPCtrlRegOperands(
true,
MI,
MF);
164 case Mips::BuildPairF64_64:
165 case Mips::ExtractElementF64_64:
171 case Mips::BuildPairF64:
172 case Mips::ExtractElementF64:
178 if (
MI.getOperand(0).isGlobal() &&
179 MI.getOperand(0).getGlobal()->getGlobalIdentifier() ==
"_mcount")
182 case Mips::JALRPseudo:
183 case Mips::JALR64Pseudo:
184 case Mips::JALR16_MM:
185 if (
MI.getOperand(2).isMCSymbol() &&
186 MI.getOperand(2).getMCSymbol()->getName() ==
"_mcount")
190 if (
MI.getOperand(3).isMCSymbol() &&
191 MI.getOperand(3).getMCSymbol()->getName() ==
"_mcount")
195 replaceUsesWithZeroReg(
MRI,
MI);
205 EVT VT =
LHS.getValueType();
234 MVT::Glue, CstOne, InGlue);
237 Mips::EXT,
DL, MVT::i32,
SDValue(DSPCtrlField, 0), OuFlag, CstOne);
256 SDValue(DSPCtrlFinal, 0), CstOne);
266 EVT ValTy =
Addr.getValueType();
276bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset(
278 unsigned ShiftAmount = 0)
const {
280 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
281 if (
isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) {
282 EVT ValTy =
Addr.getValueType();
286 dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
292 const Align Alignment(1ULL << ShiftAmount);
293 if (!
isAligned(Alignment, CN->getZExtValue()))
343 if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
344 isa<JumpTableSDNode>(Opnd0)) {
437 if (isa<FrameIndexSDNode>(
Base))
441 unsigned CnstOff = CN->getZExtValue();
442 return (CnstOff == (CnstOff & 0x3c));
506bool MipsSEDAGToDAGISel::selectVSplat(
SDNode *
N,
APInt &Imm,
507 unsigned MinSizeInBits)
const {
516 APInt SplatValue, SplatUndef;
517 unsigned SplatBitSize;
520 if (!
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
545bool MipsSEDAGToDAGISel::
547 unsigned ImmBitSize)
const {
549 EVT EltTy =
N->getValueType(0).getVectorElementType();
552 N =
N->getOperand(0);
577bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(
SDValue N,
SDValue &Imm)
const {
579 EVT EltTy =
N->getValueType(0).getVectorElementType();
582 N =
N->getOperand(0);
608bool MipsSEDAGToDAGISel::selectVSplatMaskL(
SDValue N,
SDValue &Imm)
const {
610 EVT EltTy =
N->getValueType(0).getVectorElementType();
613 N =
N->getOperand(0);
639bool MipsSEDAGToDAGISel::selectVSplatMaskR(
SDValue N,
SDValue &Imm)
const {
641 EVT EltTy =
N->getValueType(0).getVectorElementType();
644 N =
N->getOperand(0);
657bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(
SDValue N,
660 EVT EltTy =
N->getValueType(0).getVectorElementType();
663 N =
N->getOperand(0);
667 int32_t
Log2 = (~ImmValue).exactLogBase2();
679bool MipsSEDAGToDAGISel::selectVSplatImmEq1(
SDValue N)
const {
681 EVT EltTy =
N->getValueType(0).getVectorElementType();
684 N =
N->getOperand(0);
686 return selectVSplat(
N.getNode(), ImmValue, EltTy.
getSizeInBits()) &&
690bool MipsSEDAGToDAGISel::trySelect(
SDNode *
Node) {
691 unsigned Opcode =
Node->getOpcode();
711 EVT NodeTys[] = {VT, VT};
713 ? Mips::PseudoD_SELECT_I64
714 : Mips::PseudoD_SELECT_I,
725 auto *CN = cast<ConstantFPSDNode>(
Node);
726 if (
Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
729 Mips::ZERO_64, MVT::i64);
734 Mips::ZERO, MVT::i32);
736 MVT::f64, Zero, Zero));
739 Mips::ZERO, MVT::i32);
741 MVT::f64, Zero, Zero));
749 auto *CN = cast<ConstantSDNode>(
Node);
750 int64_t
Imm = CN->getSExtValue();
751 unsigned Size = CN->getValueSizeInBits(0);
770 if (Inst->Opc == Mips::LUi64)
779 for (++Inst; Inst != Seq.
end(); ++Inst) {
791 const unsigned IntrinsicOpcode =
Node->getConstantOperandVal(1);
792 switch (IntrinsicOpcode) {
796 case Intrinsic::mips_cfcmsa: {
800 getMSACtrlReg(RegIdx), MVT::i32);
804 case Intrinsic::mips_ldr_d:
805 case Intrinsic::mips_ldr_w: {
806 unsigned Op = (IntrinsicOpcode == Intrinsic::mips_ldr_d) ? Mips::LDR_D
810 assert(
Node->getNumOperands() == 4 &&
"Unexpected number of operands.");
820 "Invalid instruction operand.");
824 cast<ConstantSDNode>(
Constant)->getConstantIntValue();
831 assert(
Node->getValueType(0).is128BitVector());
844 switch (
Node->getConstantOperandVal(0)) {
848 case Intrinsic::mips_move_v:
852 Node->getValueType(0),
853 Node->getOperand(1)));
860 const unsigned IntrinsicOpcode =
Node->getConstantOperandVal(1);
861 switch (IntrinsicOpcode) {
865 case Intrinsic::mips_ctcmsa: {
870 getMSACtrlReg(RegIdx),
Value);
874 case Intrinsic::mips_str_d:
875 case Intrinsic::mips_str_w: {
876 unsigned Op = (IntrinsicOpcode == Intrinsic::mips_str_d) ? Mips::STR_D
880 assert(
Node->getNumOperands() == 5 &&
"Unexpected number of operands.");
891 "Invalid instruction operand.");
895 cast<ConstantSDNode>(
Constant)->getConstantIntValue();
913 MVT ResTy =
Node->getSimpleValueType(0);
914 assert((ResTy == MVT::f64 || ResTy == MVT::f32) &&
915 "Unsupported float type!");
917 if (ResTy == MVT::f64)
925 Opc = Mips::FABS_D64_MM;
928 Opc = Mips::FABS_D32_MM;
931 Opc = Mips::FABS_S_MM;
953 if (
Node->getValueType(0) != MVT::i32 &&
Node->getValueType(0) != MVT::i64)
956 if (
Node->getNumOperands() != 4)
963 MVT ResTy =
Node->getSimpleValueType(0);
974 if (ResTy != MVT::i32 && ResTy != MVT::i64)
978 if (ResTy == MVT::i32) {
979 if (Pos +
Size <= 32)
982 if (Pos +
Size <= 32)
984 else if (Pos < 32 && 1 <
Size)
985 Opcode = Mips::DINSM;
987 Opcode = Mips::DINSU;
1004 unsigned RdhwrOpc, DestReg;
1006 if (PtrVT == MVT::i32) {
1007 RdhwrOpc = Mips::RDHWR;
1010 RdhwrOpc = Mips::RDHWR64;
1011 DestReg = Mips::V1_64;
1043 APInt SplatValue, SplatUndef;
1044 unsigned SplatBitSize;
1058 switch (SplatBitSize) {
1062 LdiOp = Mips::LDI_B;
1063 ViaVecTy = MVT::v16i8;
1066 LdiOp = Mips::LDI_H;
1067 ViaVecTy = MVT::v8i16;
1070 LdiOp = Mips::LDI_W;
1071 ViaVecTy = MVT::v4i32;
1074 LdiOp = Mips::LDI_D;
1075 ViaVecTy = MVT::v2i64;
1091 ((
ABI.IsO32() && SplatBitSize < 64) ||
1092 (
ABI.IsN32() ||
ABI.IsN64()))) {
1098 bool Is32BitSplat =
ABI.IsO32() || SplatBitSize < 64;
1099 const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu;
1100 const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64;
1102 Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT);
1104 const unsigned FILLOp =
1107 : (SplatBitSize == 32 ? Mips::FILL_W
1108 : (SplatBitSize == 64 ? Mips::FILL_D : 0));
1110 assert(FILLOp != 0 &&
"Unknown FILL Op for splat synthesis!");
1111 assert((!
ABI.IsO32() || (FILLOp != Mips::FILL_D)) &&
1112 "Attempting to use fill.d on MIPS32!");
1120 }
else if (SplatValue.
isSignedIntN(32) && SplatBitSize == 32) {
1137 assert((
Hi ||
Lo) &&
"Zero case reached 32 bit case splat synthesis!");
1141 }
else if (SplatValue.
isSignedIntN(32) && SplatBitSize == 64 &&
1142 (
ABI.IsN32() ||
ABI.IsN64())) {
1161 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1235 Highest ?
SDValue(HiRes, 0) : ZeroVal,
1244 Mips::INSERT_W,
DL, MVT::v4i32,
SDValue(Res, 0),
1245 (Highest || Higher) ?
SDValue(HiRes, 0) : ZeroVal,
1253 Mips::COPY_TO_REGCLASS,
DL, ViaVecTy,
SDValue(Res, 0),
1257 Mips::SPLATI_D,
DL, MVT::v2i64,
SDValue(Res, 0),
1259 }
else if (
ABI.IsN64() ||
ABI.IsN32()) {
1263 const bool ResNonZero =
Hi ||
Lo;
1267 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1274 Mips::SUBREG_TO_REG,
DL, MVT::i64,
1289 const ConstantInt *Const32 = ConstantInt::get(Int32Ty, 32);
1296 }
else if (HiResNonZero) {
1298 Mips::DSLL32,
DL, MVT::i64,
SDValue(HiRes, 0),
1302 "Zero splat value handled by non-zero 64bit splat synthesis!");
1312 if (ResVecTy != ViaVecTy) {
1335bool MipsSEDAGToDAGISel::SelectInlineAsmMemoryOperand(
1337 std::vector<SDValue> &OutOps) {
1340 switch(ConstraintID) {
1347 OutOps.push_back(
Base);
1348 OutOps.push_back(
Offset);
1351 OutOps.push_back(
Op);
1361 OutOps.push_back(
Base);
1362 OutOps.push_back(
Offset);
1365 OutOps.push_back(
Op);
1374 OutOps.push_back(
Base);
1375 OutOps.push_back(
Offset);
1381 OutOps.push_back(
Base);
1382 OutOps.push_back(
Offset);
1387 OutOps.push_back(
Base);
1388 OutOps.push_back(
Offset);
1392 OutOps.push_back(
Op);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static uint64_t getConstant(const Value *IndexValue)
mir Rename Register Operands
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.
bool isNegative() const
Determine sign of this APInt.
int32_t exactLogBase2() const
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
bool isMask(unsigned numBits) const
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.
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
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...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MipsSEDAGToDAGISelLegacy(MipsTargetMachine &TM, CodeGenOptLevel OL)
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.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
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
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
const TargetLowering * getTargetLowering() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
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,...
SDValue getRegister(Register Reg, EVT VT)
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
const DataLayout & getDataLayout() const
SDValue getTargetFrameIndex(int FI, EVT VT)
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 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.
@ 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,...
@ 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.
Implement std::hash so that hash_code can be used in STL containers.
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.