diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonISelLowering.cpp')
| -rw-r--r-- | lib/Target/Hexagon/HexagonISelLowering.cpp | 1087 |
1 files changed, 525 insertions, 562 deletions
diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 3997702bc962..586363335df1 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" @@ -50,7 +51,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> #include <cassert> @@ -129,7 +129,10 @@ namespace { // Implement calling convention for Hexagon. -static bool isHvxVectorType(MVT ty); +static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 }; +static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; +static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; +static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 }; static bool CC_Hexagon(unsigned ValNo, MVT ValVT, @@ -224,19 +227,19 @@ CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT, State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return false; } - if (LocVT == MVT::v8i64 || LocVT == MVT::v16i32 || LocVT == MVT::v32i16 || + if (LocVT == MVT::v16i32 || LocVT == MVT::v32i16 || LocVT == MVT::v64i8 || LocVT == MVT::v512i1) { Offset = State.AllocateStack(64, 64); State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return false; } - if (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 || + if (LocVT == MVT::v32i32 || LocVT == MVT::v64i16 || LocVT == MVT::v128i8 || LocVT == MVT::v1024i1) { Offset = State.AllocateStack(128, 128); State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return false; } - if (LocVT == MVT::v32i64 || LocVT == MVT::v64i32 || LocVT == MVT::v128i16 || + if (LocVT == MVT::v64i32 || LocVT == MVT::v128i16 || LocVT == MVT::v256i8) { Offset = State.AllocateStack(256, 256); State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); @@ -291,7 +294,8 @@ static bool CC_Hexagon (unsigned ValNo, MVT ValVT, MVT LocVT, return false; } - if (isHvxVectorType(LocVT)) { + auto &HST = State.getMachineFunction().getSubtarget<HexagonSubtarget>(); + if (HST.isHVXVectorType(LocVT)) { if (!CC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) return false; } @@ -356,11 +360,9 @@ static bool CC_HexagonVector(unsigned ValNo, MVT ValVT, }; auto &MF = State.getMachineFunction(); auto &HST = MF.getSubtarget<HexagonSubtarget>(); - bool UseHVX = HST.useHVXOps(); - bool UseHVXDbl = HST.useHVXDblOps(); - if ((UseHVX && !UseHVXDbl) && - (LocVT == MVT::v8i64 || LocVT == MVT::v16i32 || LocVT == MVT::v32i16 || + if (HST.useHVX64BOps() && + (LocVT == MVT::v16i32 || LocVT == MVT::v32i16 || LocVT == MVT::v64i8 || LocVT == MVT::v512i1)) { if (unsigned Reg = State.AllocateReg(VecLstS)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); @@ -370,9 +372,8 @@ static bool CC_HexagonVector(unsigned ValNo, MVT ValVT, State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return false; } - if ((UseHVX && !UseHVXDbl) && - (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 || - LocVT == MVT::v128i8)) { + if (HST.useHVX64BOps() && (LocVT == MVT::v32i32 || + LocVT == MVT::v64i16 || LocVT == MVT::v128i8)) { if (unsigned Reg = State.AllocateReg(VecLstD)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); return false; @@ -382,9 +383,8 @@ static bool CC_HexagonVector(unsigned ValNo, MVT ValVT, return false; } // 128B Mode - if ((UseHVX && UseHVXDbl) && - (LocVT == MVT::v32i64 || LocVT == MVT::v64i32 || LocVT == MVT::v128i16 || - LocVT == MVT::v256i8)) { + if (HST.useHVX128BOps() && (LocVT == MVT::v64i32 || + LocVT == MVT::v128i16 || LocVT == MVT::v256i8)) { if (unsigned Reg = State.AllocateReg(VecLstD)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); return false; @@ -393,8 +393,8 @@ static bool CC_HexagonVector(unsigned ValNo, MVT ValVT, State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); return false; } - if ((UseHVX && UseHVXDbl) && - (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 || + if (HST.useHVX128BOps() && + (LocVT == MVT::v32i32 || LocVT == MVT::v64i16 || LocVT == MVT::v128i8 || LocVT == MVT::v1024i1)) { if (unsigned Reg = State.AllocateReg(VecLstS)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); @@ -412,8 +412,6 @@ static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT, ISD::ArgFlagsTy ArgFlags, CCState &State) { auto &MF = State.getMachineFunction(); auto &HST = MF.getSubtarget<HexagonSubtarget>(); - bool UseHVX = HST.useHVXOps(); - bool UseHVXDbl = HST.useHVXDblOps(); if (LocVT == MVT::i1) { // Return values of type MVT::i1 still need to be assigned to R0, but @@ -436,19 +434,18 @@ static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT, LocVT = MVT::i64; LocInfo = CCValAssign::BCvt; } else if (LocVT == MVT::v64i8 || LocVT == MVT::v32i16 || - LocVT == MVT::v16i32 || LocVT == MVT::v8i64 || - LocVT == MVT::v512i1) { + LocVT == MVT::v16i32 || LocVT == MVT::v512i1) { LocVT = MVT::v16i32; ValVT = MVT::v16i32; LocInfo = CCValAssign::Full; } else if (LocVT == MVT::v128i8 || LocVT == MVT::v64i16 || - LocVT == MVT::v32i32 || LocVT == MVT::v16i64 || - (LocVT == MVT::v1024i1 && UseHVX && UseHVXDbl)) { + LocVT == MVT::v32i32 || + (LocVT == MVT::v1024i1 && HST.useHVX128BOps())) { LocVT = MVT::v32i32; ValVT = MVT::v32i32; LocInfo = CCValAssign::Full; } else if (LocVT == MVT::v256i8 || LocVT == MVT::v128i16 || - LocVT == MVT::v64i32 || LocVT == MVT::v32i64) { + LocVT == MVT::v64i32) { LocVT = MVT::v64i32; ValVT = MVT::v64i32; LocInfo = CCValAssign::Full; @@ -506,8 +503,6 @@ static bool RetCC_HexagonVector(unsigned ValNo, MVT ValVT, ISD::ArgFlagsTy ArgFlags, CCState &State) { auto &MF = State.getMachineFunction(); auto &HST = MF.getSubtarget<HexagonSubtarget>(); - bool UseHVX = HST.useHVXOps(); - bool UseHVXDbl = HST.useHVXDblOps(); if (LocVT == MVT::v16i32) { if (unsigned Reg = State.AllocateReg(Hexagon::V0)) { @@ -515,7 +510,7 @@ static bool RetCC_HexagonVector(unsigned ValNo, MVT ValVT, return false; } } else if (LocVT == MVT::v32i32) { - unsigned Req = (UseHVX && UseHVXDbl) ? Hexagon::V0 : Hexagon::W0; + unsigned Req = HST.useHVX128BOps() ? Hexagon::V0 : Hexagon::W0; if (unsigned Reg = State.AllocateReg(Req)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); return false; @@ -561,28 +556,6 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, MachinePointerInfo(), MachinePointerInfo()); } -static bool isHvxVectorType(MVT Ty) { - switch (Ty.SimpleTy) { - case MVT::v8i64: - case MVT::v16i32: - case MVT::v32i16: - case MVT::v64i8: - case MVT::v16i64: - case MVT::v32i32: - case MVT::v64i16: - case MVT::v128i8: - case MVT::v32i64: - case MVT::v64i32: - case MVT::v128i16: - case MVT::v256i8: - case MVT::v512i1: - case MVT::v1024i1: - return true; - default: - return false; - } -} - bool HexagonTargetLowering::CanLowerReturn( CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, @@ -685,13 +658,14 @@ SDValue HexagonTargetLowering::LowerCallResult( // as an implicit def to the call (EmitMachineNode). RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1); Glue = TPR.getValue(1); + Chain = TPR.getValue(0); } else { RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), RVLocs[i].getValVT(), Glue); Glue = RetVal.getValue(2); + Chain = RetVal.getValue(1); } InVals.push_back(RetVal.getValue(0)); - Chain = RetVal.getValue(1); } return Chain; @@ -743,12 +717,12 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, else CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon); - auto Attr = MF.getFunction()->getFnAttribute("disable-tail-calls"); + auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls"); if (Attr.getValueAsString() == "true") IsTailCall = false; if (IsTailCall) { - bool StructAttrFlag = MF.getFunction()->hasStructRetAttr(); + bool StructAttrFlag = MF.getFunction().hasStructRetAttr(); IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, IsVarArg, IsStructRet, StructAttrFlag, @@ -781,7 +755,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDValue Arg = OutVals[i]; ISD::ArgFlagsTy Flags = Outs[i].Flags; // Record if we need > 8 byte alignment on an argument. - bool ArgAlign = isHvxVectorType(VA.getValVT()); + bool ArgAlign = Subtarget.isHVXVectorType(VA.getValVT()); NeedsArgAlign |= ArgAlign; // Promote the value if needed. @@ -835,9 +809,9 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, DEBUG(dbgs() << "Function needs byte stack align due to call args\n"); // V6 vectors passed by value have 64 or 128 byte alignment depending // on whether we are 64 byte vector mode or 128 byte. - bool UseHVXDbl = Subtarget.useHVXDblOps(); + bool UseHVX128B = Subtarget.useHVX128BOps(); assert(Subtarget.useHVXOps()); - const unsigned ObjAlign = UseHVXDbl ? 128 : 64; + const unsigned ObjAlign = UseHVX128B ? 128 : 64; LargestAlignSeen = std::max(LargestAlignSeen, ObjAlign); MFI.ensureMaxAlignment(LargestAlignSeen); } @@ -947,18 +921,16 @@ static bool getIndexedAddressParts(SDNode *Ptr, EVT VT, return false; auto &HST = static_cast<const HexagonSubtarget&>(DAG.getSubtarget()); - bool UseHVX = HST.useHVXOps(); - bool UseHVXDbl = HST.useHVXDblOps(); - bool ValidHVXDblType = - (UseHVX && UseHVXDbl) && (VT == MVT::v32i32 || VT == MVT::v16i64 || + bool ValidHVX128BType = + HST.useHVX128BOps() && (VT == MVT::v32i32 || VT == MVT::v64i16 || VT == MVT::v128i8); bool ValidHVXType = - UseHVX && !UseHVXDbl && (VT == MVT::v16i32 || VT == MVT::v8i64 || + HST.useHVX64BOps() && (VT == MVT::v16i32 || VT == MVT::v32i16 || VT == MVT::v64i8); - if (ValidHVXDblType || ValidHVXType || - VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { + if (ValidHVX128BType || ValidHVXType || VT == MVT::i64 || VT == MVT::i32 || + VT == MVT::i16 || VT == MVT::i8) { IsInc = (Ptr->getOpcode() == ISD::ADD); Base = Ptr->getOperand(0); Offset = Ptr->getOperand(1); @@ -979,7 +951,6 @@ bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, SelectionDAG &DAG) const { EVT VT; - SDValue Ptr; if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { VT = LD->getMemoryVT(); @@ -1145,7 +1116,6 @@ SDValue HexagonTargetLowering::LowerFormalArguments( // callee return the result direclty through R0/R1. SmallVector<SDValue, 8> MemOps; - bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps(); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -1162,7 +1132,7 @@ SDValue HexagonTargetLowering::LowerFormalArguments( EVT RegVT = VA.getLocVT(); if (RegVT == MVT::i8 || RegVT == MVT::i16 || RegVT == MVT::i32 || RegVT == MVT::f32) { - unsigned VReg = + unsigned VReg = RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); @@ -1188,38 +1158,38 @@ SDValue HexagonTargetLowering::LowerFormalArguments( InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); // Single Vector - } else if ((RegVT == MVT::v8i64 || RegVT == MVT::v16i32 || + } else if ((RegVT == MVT::v16i32 || RegVT == MVT::v32i16 || RegVT == MVT::v64i8)) { unsigned VReg = - RegInfo.createVirtualRegister(&Hexagon::VectorRegsRegClass); + RegInfo.createVirtualRegister(&Hexagon::HvxVRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); - } else if (UseHVX && UseHVXDbl && - ((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 || - RegVT == MVT::v64i16 || RegVT == MVT::v128i8))) { + } else if (Subtarget.useHVX128BOps() && + ((RegVT == MVT::v32i32 || + RegVT == MVT::v64i16 || RegVT == MVT::v128i8))) { unsigned VReg = - RegInfo.createVirtualRegister(&Hexagon::VectorRegs128BRegClass); + RegInfo.createVirtualRegister(&Hexagon::HvxVRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); // Double Vector - } else if ((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 || + } else if ((RegVT == MVT::v32i32 || RegVT == MVT::v64i16 || RegVT == MVT::v128i8)) { unsigned VReg = - RegInfo.createVirtualRegister(&Hexagon::VecDblRegsRegClass); + RegInfo.createVirtualRegister(&Hexagon::HvxWRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); - } else if (UseHVX && UseHVXDbl && - ((RegVT == MVT::v32i64 || RegVT == MVT::v64i32 || - RegVT == MVT::v128i16 || RegVT == MVT::v256i8))) { + } else if (Subtarget.useHVX128BOps() && + ((RegVT == MVT::v64i32 || + RegVT == MVT::v128i16 || RegVT == MVT::v256i8))) { unsigned VReg = - RegInfo.createVirtualRegister(&Hexagon::VecDblRegs128BRegClass); + RegInfo.createVirtualRegister(&Hexagon::HvxWRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); } else if (RegVT == MVT::v512i1 || RegVT == MVT::v1024i1) { assert(0 && "need to support VecPred regs"); unsigned VReg = - RegInfo.createVirtualRegister(&Hexagon::VecPredRegsRegClass); + RegInfo.createVirtualRegister(&Hexagon::HvxQRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); } else { @@ -1302,6 +1272,9 @@ SDValue HexagonTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(ty(LHS))) + return LowerHvxSetCC(Op, DAG); + SDValue Cmp = Op.getOperand(2); ISD::CondCode CC = cast<CondCodeSDNode>(Cmp)->get(); @@ -1364,10 +1337,44 @@ HexagonTargetLowering::LowerVSELECT(SDValue Op, SelectionDAG &DAG) const { return SDValue(); } +static Constant *convert_i1_to_i8(const Constant *ConstVal) { + SmallVector<Constant *, 128> NewConst; + const ConstantVector *CV = dyn_cast<ConstantVector>(ConstVal); + if (!CV) + return nullptr; + + LLVMContext &Ctx = ConstVal->getContext(); + IRBuilder<> IRB(Ctx); + unsigned NumVectorElements = CV->getNumOperands(); + assert(isPowerOf2_32(NumVectorElements) && + "conversion only supported for pow2 VectorSize!"); + + for (unsigned i = 0; i < NumVectorElements / 8; ++i) { + uint8_t x = 0; + for (unsigned j = 0; j < 8; ++j) { + uint8_t y = CV->getOperand(i * 8 + j)->getUniqueInteger().getZExtValue(); + x |= y << (7 - j); + } + assert((x == 0 || x == 255) && "Either all 0's or all 1's expected!"); + NewConst.push_back(IRB.getInt8(x)); + } + return ConstantVector::get(NewConst); +} + SDValue HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { EVT ValTy = Op.getValueType(); ConstantPoolSDNode *CPN = cast<ConstantPoolSDNode>(Op); + Constant *CVal = nullptr; + bool isVTi1Type = false; + if (const Constant *ConstVal = dyn_cast<Constant>(CPN->getConstVal())) { + Type *CValTy = ConstVal->getType(); + if (CValTy->isVectorTy() && + CValTy->getVectorElementType()->isIntegerTy(1)) { + CVal = convert_i1_to_i8(ConstVal); + isVTi1Type = (CVal != nullptr); + } + } unsigned Align = CPN->getAlignment(); bool IsPositionIndependent = isPositionIndependent(); unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0; @@ -1377,6 +1384,8 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { if (CPN->isMachineConstantPoolEntry()) T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Align, Offset, TF); + else if (isVTi1Type) + T = DAG.getTargetConstantPool(CVal, ValTy, Align, Offset, TF); else T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Align, Offset, TF); @@ -1675,9 +1684,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, Subtarget(ST) { bool IsV4 = !Subtarget.hasV5TOps(); auto &HRI = *Subtarget.getRegisterInfo(); - bool UseHVX = Subtarget.useHVXOps(); - bool UseHVXSgl = Subtarget.useHVXSglOps(); - bool UseHVXDbl = Subtarget.useHVXDblOps(); setPrefLoopAlignment(4); setPrefFunctionAlignment(4); @@ -1722,26 +1728,28 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, } if (Subtarget.hasV60TOps()) { - if (Subtarget.useHVXSglOps()) { - addRegisterClass(MVT::v64i8, &Hexagon::VectorRegsRegClass); - addRegisterClass(MVT::v32i16, &Hexagon::VectorRegsRegClass); - addRegisterClass(MVT::v16i32, &Hexagon::VectorRegsRegClass); - addRegisterClass(MVT::v8i64, &Hexagon::VectorRegsRegClass); - addRegisterClass(MVT::v128i8, &Hexagon::VecDblRegsRegClass); - addRegisterClass(MVT::v64i16, &Hexagon::VecDblRegsRegClass); - addRegisterClass(MVT::v32i32, &Hexagon::VecDblRegsRegClass); - addRegisterClass(MVT::v16i64, &Hexagon::VecDblRegsRegClass); - addRegisterClass(MVT::v512i1, &Hexagon::VecPredRegsRegClass); - } else if (Subtarget.useHVXDblOps()) { - addRegisterClass(MVT::v128i8, &Hexagon::VectorRegs128BRegClass); - addRegisterClass(MVT::v64i16, &Hexagon::VectorRegs128BRegClass); - addRegisterClass(MVT::v32i32, &Hexagon::VectorRegs128BRegClass); - addRegisterClass(MVT::v16i64, &Hexagon::VectorRegs128BRegClass); - addRegisterClass(MVT::v256i8, &Hexagon::VecDblRegs128BRegClass); - addRegisterClass(MVT::v128i16, &Hexagon::VecDblRegs128BRegClass); - addRegisterClass(MVT::v64i32, &Hexagon::VecDblRegs128BRegClass); - addRegisterClass(MVT::v32i64, &Hexagon::VecDblRegs128BRegClass); - addRegisterClass(MVT::v1024i1, &Hexagon::VecPredRegs128BRegClass); + if (Subtarget.useHVX64BOps()) { + addRegisterClass(MVT::v64i8, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v512i1, &Hexagon::HvxQRRegClass); + } else if (Subtarget.useHVX128BOps()) { + addRegisterClass(MVT::v128i8, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v64i16, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v32i32, &Hexagon::HvxVRRegClass); + addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass); + addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass); + addRegisterClass(MVT::v1024i1, &Hexagon::HvxQRRegClass); } } @@ -1946,6 +1954,15 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SRL, VT, Custom); } + // Extending loads from (native) vectors of i8 into (native) vectors of i16 + // are legal. + setLoadExtAction(ISD::EXTLOAD, MVT::v2i16, MVT::v2i8, Legal); + setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i16, MVT::v2i8, Legal); + setLoadExtAction(ISD::SEXTLOAD, MVT::v2i16, MVT::v2i8, Legal); + setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Legal); + setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Legal); + setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Legal); + // Types natively supported: for (MVT NativeVT : {MVT::v2i1, MVT::v4i1, MVT::v8i1, MVT::v32i1, MVT::v64i1, MVT::v4i8, MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v1i32, @@ -1970,36 +1987,68 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i16, Custom); setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i8, Custom); - if (UseHVX) { - if (UseHVXSgl) { - setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i8, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i16, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i32, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v16i64, Custom); - // We try to generate the vpack{e/o} instructions. If we fail - // we fall back upon ExpandOp. - setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v64i8, Custom); - setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v32i16, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v64i8, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v32i16, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v16i32, Custom); - } else if (UseHVXDbl) { - setOperationAction(ISD::CONCAT_VECTORS, MVT::v256i8, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i16, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i32, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i64, Custom); - // We try to generate the vpack{e/o} instructions. If we fail - // we fall back upon ExpandOp. - setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v128i8, Custom); - setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v64i16, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v4i32, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v128i8, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v64i16, Custom); - setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v32i32, Custom); - } else { - llvm_unreachable("Unrecognized HVX mode"); + auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) { + setOperationAction(Opc, FromTy, Promote); + AddPromotedToType(Opc, FromTy, ToTy); + }; + + if (Subtarget.useHVXOps()) { + bool Use64b = Subtarget.useHVX64BOps(); + ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128; + ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128; + MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8; + MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8; + + setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal); + setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal); + setOperationAction(ISD::CONCAT_VECTORS, ByteW, Legal); + setOperationAction(ISD::AND, ByteV, Legal); + setOperationAction(ISD::OR, ByteV, Legal); + setOperationAction(ISD::XOR, ByteV, Legal); + + for (MVT T : LegalV) { + setIndexedLoadAction(ISD::POST_INC, T, Legal); + setIndexedStoreAction(ISD::POST_INC, T, Legal); + + setOperationAction(ISD::ADD, T, Legal); + setOperationAction(ISD::SUB, T, Legal); + setOperationAction(ISD::VSELECT, T, Legal); + if (T != ByteV) { + setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); + setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); + } + + setOperationAction(ISD::MUL, T, Custom); + setOperationAction(ISD::SETCC, T, Custom); + setOperationAction(ISD::BUILD_VECTOR, T, Custom); + setOperationAction(ISD::INSERT_SUBVECTOR, T, Custom); + setOperationAction(ISD::INSERT_VECTOR_ELT, T, Custom); + setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom); + if (T != ByteV) + setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom); + } + + for (MVT T : LegalV) { + if (T == ByteV) + continue; + // Promote all shuffles and concats to operate on vectors of bytes. + setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV); + setPromoteTo(ISD::CONCAT_VECTORS, T, ByteV); + setPromoteTo(ISD::AND, T, ByteV); + setPromoteTo(ISD::OR, T, ByteV); + setPromoteTo(ISD::XOR, T, ByteV); + } + + for (MVT T : LegalW) { + if (T == ByteW) + continue; + // Promote all shuffles and concats to operate on vectors of bytes. + setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW); + setPromoteTo(ISD::CONCAT_VECTORS, T, ByteW); } } + // Subtarget-specific operation actions. // if (Subtarget.hasV5TOps()) { @@ -2061,20 +2110,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setIndexedStoreAction(ISD::POST_INC, VT, Legal); } - if (UseHVXSgl) { - for (MVT VT : {MVT::v64i8, MVT::v32i16, MVT::v16i32, MVT::v8i64, - MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64}) { - setIndexedLoadAction(ISD::POST_INC, VT, Legal); - setIndexedStoreAction(ISD::POST_INC, VT, Legal); - } - } else if (UseHVXDbl) { - for (MVT VT : {MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64, - MVT::v256i8, MVT::v128i16, MVT::v64i32, MVT::v32i64}) { - setIndexedLoadAction(ISD::POST_INC, VT, Legal); - setIndexedStoreAction(ISD::POST_INC, VT, Legal); - } - } - computeRegisterProperties(&HRI); // @@ -2208,7 +2243,6 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { case HexagonISD::INSERT: return "HexagonISD::INSERT"; case HexagonISD::INSERTRP: return "HexagonISD::INSERTRP"; case HexagonISD::JT: return "HexagonISD::JT"; - case HexagonISD::PACKHL: return "HexagonISD::PACKHL"; case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG"; case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN"; case HexagonISD::VCOMBINE: return "HexagonISD::VCOMBINE"; @@ -2218,12 +2252,54 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { case HexagonISD::VASR: return "HexagonISD::VASR"; case HexagonISD::VLSR: return "HexagonISD::VLSR"; case HexagonISD::VSPLAT: return "HexagonISD::VSPLAT"; + case HexagonISD::VEXTRACTW: return "HexagonISD::VEXTRACTW"; + case HexagonISD::VINSERTW0: return "HexagonISD::VINSERTW0"; + case HexagonISD::VROR: return "HexagonISD::VROR"; case HexagonISD::READCYCLE: return "HexagonISD::READCYCLE"; case HexagonISD::OP_END: break; } return nullptr; } +/// Given an intrinsic, checks if on the target the intrinsic will need to map +/// to a MemIntrinsicNode (touches memory). If this is the case, it returns +/// true and store the intrinsic information into the IntrinsicInfo that was +/// passed to the function. +bool HexagonTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, + const CallInst &I, + MachineFunction &MF, + unsigned Intrinsic) const { + switch (Intrinsic) { + case Intrinsic::hexagon_V6_vgathermw: + case Intrinsic::hexagon_V6_vgathermw_128B: + case Intrinsic::hexagon_V6_vgathermh: + case Intrinsic::hexagon_V6_vgathermh_128B: + case Intrinsic::hexagon_V6_vgathermhw: + case Intrinsic::hexagon_V6_vgathermhw_128B: + case Intrinsic::hexagon_V6_vgathermwq: + case Intrinsic::hexagon_V6_vgathermwq_128B: + case Intrinsic::hexagon_V6_vgathermhq: + case Intrinsic::hexagon_V6_vgathermhq_128B: + case Intrinsic::hexagon_V6_vgathermhwq: + case Intrinsic::hexagon_V6_vgathermhwq_128B: { + const Module &M = *I.getParent()->getParent()->getParent(); + Info.opc = ISD::INTRINSIC_W_CHAIN; + Type *VecTy = I.getArgOperand(1)->getType(); + Info.memVT = MVT::getVT(VecTy); + Info.ptrVal = I.getArgOperand(0); + Info.offset = 0; + Info.align = M.getDataLayout().getTypeAllocSizeInBits(VecTy) / 8; + Info.flags = MachineMemOperand::MOLoad | + MachineMemOperand::MOStore | + MachineMemOperand::MOVolatile; + return true; + } + default: + break; + } + return false; +} + bool HexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const { EVT MTy1 = EVT::getEVT(Ty1); EVT MTy2 = EVT::getEVT(Ty2); @@ -2245,44 +2321,24 @@ bool HexagonTargetLowering::isFMAFasterThanFMulAndFAdd(EVT VT) const { // Should we expand the build vector with shuffles? bool HexagonTargetLowering::shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const { - // Hexagon vector shuffle operates on element sizes of bytes or halfwords - EVT EltVT = VT.getVectorElementType(); - int EltBits = EltVT.getSizeInBits(); - if ((EltBits != 8) && (EltBits != 16)) - return false; - - return TargetLowering::shouldExpandBuildVectorWithShuffles(VT, DefinedValues); + return false; } -static StridedLoadKind isStridedLoad(const ArrayRef<int> &Mask) { - int even_start = -2; - int odd_start = -1; - size_t mask_len = Mask.size(); - for (auto idx : Mask) { - if ((idx - even_start) == 2) - even_start = idx; - else - break; - } - if (even_start == (int)(mask_len * 2) - 2) - return StridedLoadKind::Even; - for (auto idx : Mask) { - if ((idx - odd_start) == 2) - odd_start = idx; - else - break; - } - if (odd_start == (int)(mask_len * 2) - 1) - return StridedLoadKind::Odd; - - return StridedLoadKind::NoPattern; +bool HexagonTargetLowering::isShuffleMaskLegal(ArrayRef<int> Mask, + EVT VT) const { + return true; } -bool HexagonTargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &Mask, - EVT VT) const { - if (Subtarget.useHVXOps()) - return isStridedLoad(Mask) != StridedLoadKind::NoPattern; - return true; +TargetLoweringBase::LegalizeTypeAction +HexagonTargetLowering::getPreferredVectorAction(EVT VT) const { + if (Subtarget.useHVXOps()) { + // If the size of VT is at least half of the vector length, + // widen the vector. Note: the threshold was not selected in + // any scientific way. + if (VT.getSizeInBits() >= Subtarget.getVectorLength()*8/2) + return TargetLoweringBase::TypeWidenVector; + } + return TargetLowering::getPreferredVectorAction(VT); } // Lower a vector shuffle (V1, V2, V3). V1 and V2 are the two vectors @@ -2295,7 +2351,6 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) SDValue V2 = Op.getOperand(1); SDLoc dl(Op); EVT VT = Op.getValueType(); - bool UseHVX = Subtarget.useHVXOps(); if (V2.isUndef()) V2 = V1; @@ -2327,27 +2382,6 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) DAG.getConstant(Lane, dl, MVT::i32)); } - if (UseHVX) { - ArrayRef<int> Mask = SVN->getMask(); - size_t MaskLen = Mask.size(); - unsigned SizeInBits = VT.getScalarSizeInBits() * MaskLen; - - if ((Subtarget.useHVXSglOps() && SizeInBits == 64 * 8) || - (Subtarget.useHVXDblOps() && SizeInBits == 128 * 8)) { - StridedLoadKind Pattern = isStridedLoad(Mask); - if (Pattern == StridedLoadKind::NoPattern) - return SDValue(); - - unsigned Opc = Pattern == StridedLoadKind::Even ? HexagonISD::VPACKE - : HexagonISD::VPACKO; - return DAG.getNode(Opc, dl, VT, {Op.getOperand(1), Op.getOperand(0)}); - } - // We used to assert in the "else" part here, but that is bad for Halide - // Halide creates intermediate double registers by interleaving two - // concatenated vector registers. The interleaving requires vector_shuffle - // nodes and we shouldn't barf on a double register result of a - // vector_shuffle because it is most likely an intermediate result. - } // FIXME: We need to support more general vector shuffles. See // below the comment from the ARM backend that deals in the general // case with the vector shuffles. For now, let expand handle these. @@ -2430,392 +2464,314 @@ HexagonTargetLowering::LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const { } SDValue -HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { - BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode()); - SDLoc dl(Op); - EVT VT = Op.getValueType(); - - unsigned Size = VT.getSizeInBits(); +HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl, + MVT VecTy, SelectionDAG &DAG) const { + MVT ElemTy = VecTy.getVectorElementType(); + assert(VecTy.getVectorNumElements() == Elem.size()); - // Only handle vectors of 64 bits or shorter. - if (Size > 64) - return SDValue(); - - unsigned NElts = BVN->getNumOperands(); - - // Try to generate a SPLAT instruction. - if (VT == MVT::v4i8 || VT == MVT::v4i16 || VT == MVT::v2i32) { - APInt APSplatBits, APSplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - if (BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize, - HasAnyUndefs, 0, false)) { - if (SplatBitSize == VT.getVectorElementType().getSizeInBits()) { - unsigned ZV = APSplatBits.getZExtValue(); - assert(SplatBitSize <= 32 && "Can only handle up to i32"); - // Sign-extend the splat value from SplatBitSize to 32. - int32_t SV = SplatBitSize < 32 - ? int32_t(ZV << (32-SplatBitSize)) >> (32-SplatBitSize) - : int32_t(ZV); - return DAG.getNode(HexagonISD::VSPLAT, dl, VT, - DAG.getConstant(SV, dl, MVT::i32)); - } - } - } - - // Try to generate COMBINE to build v2i32 vectors. - if (VT.getSimpleVT() == MVT::v2i32) { - SDValue V0 = BVN->getOperand(0); - SDValue V1 = BVN->getOperand(1); - - if (V0.isUndef()) - V0 = DAG.getConstant(0, dl, MVT::i32); - if (V1.isUndef()) - V1 = DAG.getConstant(0, dl, MVT::i32); - - ConstantSDNode *C0 = dyn_cast<ConstantSDNode>(V0); - ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(V1); - // If the element isn't a constant, it is in a register: - // generate a COMBINE Register Register instruction. - if (!C0 || !C1) - return DAG.getNode(HexagonISD::COMBINE, dl, VT, V1, V0); - - // If one of the operands is an 8 bit integer constant, generate - // a COMBINE Immediate Immediate instruction. - if (isInt<8>(C0->getSExtValue()) || - isInt<8>(C1->getSExtValue())) - return DAG.getNode(HexagonISD::COMBINE, dl, VT, V1, V0); + SmallVector<ConstantSDNode*,4> Consts; + bool AllConst = true; + for (SDValue V : Elem) { + if (isUndef(V)) + V = DAG.getConstant(0, dl, ElemTy); + auto *C = dyn_cast<ConstantSDNode>(V.getNode()); + Consts.push_back(C); + AllConst = AllConst && C != nullptr; } - // Try to generate a S2_packhl to build v2i16 vectors. - if (VT.getSimpleVT() == MVT::v2i16) { - for (unsigned i = 0, e = NElts; i != e; ++i) { - if (BVN->getOperand(i).isUndef()) - continue; - ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(BVN->getOperand(i)); - // If the element isn't a constant, it is in a register: - // generate a S2_packhl instruction. - if (!Cst) { - SDValue pack = DAG.getNode(HexagonISD::PACKHL, dl, MVT::v4i16, - BVN->getOperand(1), BVN->getOperand(0)); + unsigned First, Num = Elem.size(); + for (First = 0; First != Num; ++First) + if (!isUndef(Elem[First])) + break; + if (First == Num) + return DAG.getUNDEF(VecTy); - return DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::v2i16, - pack); - } + if (ElemTy == MVT::i16) { + assert(Elem.size() == 2); + if (AllConst) { + uint32_t V = (Consts[0]->getZExtValue() & 0xFFFF) | + Consts[1]->getZExtValue() << 16; + return DAG.getBitcast(MVT::v2i16, DAG.getConstant(V, dl, MVT::i32)); } + SDValue N = getNode(Hexagon::A2_combine_ll, dl, MVT::i32, + {Elem[1], Elem[0]}, DAG); + return DAG.getBitcast(MVT::v2i16, N); } - // In the general case, generate a CONST32 or a CONST64 for constant vectors, - // and insert_vector_elt for all the other cases. - uint64_t Res = 0; - unsigned EltSize = Size / NElts; - SDValue ConstVal; - uint64_t Mask = ~uint64_t(0ULL) >> (64 - EltSize); - bool HasNonConstantElements = false; + // First try generating a constant. + assert(ElemTy == MVT::i8 && Num == 4); + if (AllConst) { + int32_t V = (Consts[0]->getZExtValue() & 0xFF) | + (Consts[1]->getZExtValue() & 0xFF) << 8 | + (Consts[1]->getZExtValue() & 0xFF) << 16 | + Consts[2]->getZExtValue() << 24; + return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32)); + } - for (unsigned i = 0, e = NElts; i != e; ++i) { - // LLVM's BUILD_VECTOR operands are in Little Endian mode, whereas Hexagon's - // combine, const64, etc. are Big Endian. - unsigned OpIdx = NElts - i - 1; - SDValue Operand = BVN->getOperand(OpIdx); - if (Operand.isUndef()) + // Then try splat. + bool IsSplat = true; + for (unsigned i = 0; i != Num; ++i) { + if (i == First) continue; - - int64_t Val = 0; - if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Operand)) - Val = Cst->getSExtValue(); - else - HasNonConstantElements = true; - - Val &= Mask; - Res = (Res << EltSize) | Val; + if (Elem[i] == Elem[First] || isUndef(Elem[i])) + continue; + IsSplat = false; + break; } + if (IsSplat) + return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Elem[First]); - if (Size > 64) - return SDValue(); + // Generate + // (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) | + // (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16 + SDValue S8 = DAG.getConstant(8, dl, MVT::i32); + SDValue V0 = DAG.getZeroExtendInReg(Elem[0], dl, MVT::i8); + SDValue V1 = DAG.getZeroExtendInReg(Elem[1], dl, MVT::i8); + SDValue V2 = DAG.getZeroExtendInReg(Elem[2], dl, MVT::i8); + SDValue V3 = DAG.getZeroExtendInReg(Elem[3], dl, MVT::i8); - if (Size == 64) - ConstVal = DAG.getConstant(Res, dl, MVT::i64); - else - ConstVal = DAG.getConstant(Res, dl, MVT::i32); + SDValue V4 = DAG.getNode(ISD::SHL, dl, MVT::i32, {V1, S8}); + SDValue V5 = DAG.getNode(ISD::SHL, dl, MVT::i32, {V3, S8}); + SDValue V6 = DAG.getNode(ISD::OR, dl, MVT::i32, {V0, V4}); + SDValue V7 = DAG.getNode(ISD::OR, dl, MVT::i32, {V2, V5}); - // When there are non constant operands, add them with INSERT_VECTOR_ELT to - // ConstVal, the constant part of the vector. - if (HasNonConstantElements) { - EVT EltVT = VT.getVectorElementType(); - SDValue Width = DAG.getConstant(EltVT.getSizeInBits(), dl, MVT::i64); - SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width, - DAG.getConstant(32, dl, MVT::i64)); + SDValue T0 = getNode(Hexagon::A2_combine_ll, dl, MVT::i32, {V7, V6}, DAG); + return DAG.getBitcast(MVT::v4i8, T0); +} - for (unsigned i = 0, e = NElts; i != e; ++i) { - // LLVM's BUILD_VECTOR operands are in Little Endian mode, whereas Hexagon - // is Big Endian. - unsigned OpIdx = NElts - i - 1; - SDValue Operand = BVN->getOperand(OpIdx); - if (isa<ConstantSDNode>(Operand)) - // This operand is already in ConstVal. - continue; +SDValue +HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl, + MVT VecTy, SelectionDAG &DAG) const { + MVT ElemTy = VecTy.getVectorElementType(); + assert(VecTy.getVectorNumElements() == Elem.size()); - if (VT.getSizeInBits() == 64 && - Operand.getValueSizeInBits() == 32) { - SDValue C = DAG.getConstant(0, dl, MVT::i32); - Operand = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, Operand); - } + SmallVector<ConstantSDNode*,8> Consts; + bool AllConst = true; + for (SDValue V : Elem) { + if (isUndef(V)) + V = DAG.getConstant(0, dl, ElemTy); + auto *C = dyn_cast<ConstantSDNode>(V.getNode()); + Consts.push_back(C); + AllConst = AllConst && C != nullptr; + } - SDValue Idx = DAG.getConstant(OpIdx, dl, MVT::i64); - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i64, Idx, Width); - SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset); - const SDValue Ops[] = {ConstVal, Operand, Combined}; + unsigned First, Num = Elem.size(); + for (First = 0; First != Num; ++First) + if (!isUndef(Elem[First])) + break; + if (First == Num) + return DAG.getUNDEF(VecTy); - if (VT.getSizeInBits() == 32) - ConstVal = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, Ops); - else - ConstVal = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, Ops); + // First try splat if possible. + if (ElemTy == MVT::i16) { + bool IsSplat = true; + for (unsigned i = 0; i != Num; ++i) { + if (i == First) + continue; + if (Elem[i] == Elem[First] || isUndef(Elem[i])) + continue; + IsSplat = false; + break; } + if (IsSplat) + return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Elem[First]); + } + + // Then try constant. + if (AllConst) { + uint64_t Val = 0; + unsigned W = ElemTy.getSizeInBits(); + uint64_t Mask = (ElemTy == MVT::i8) ? 0xFFull + : (ElemTy == MVT::i16) ? 0xFFFFull : 0xFFFFFFFFull; + for (unsigned i = 0; i != Num; ++i) + Val = (Val << W) | (Consts[i]->getZExtValue() & Mask); + SDValue V0 = DAG.getConstant(Val, dl, MVT::i64); + return DAG.getBitcast(VecTy, V0); } - return DAG.getNode(ISD::BITCAST, dl, VT, ConstVal); + // Build two 32-bit vectors and concatenate. + MVT HalfTy = MVT::getVectorVT(ElemTy, Num/2); + SDValue L = (ElemTy == MVT::i32) + ? Elem[0] + : buildVector32({Elem.data(), Num/2}, dl, HalfTy, DAG); + SDValue H = (ElemTy == MVT::i32) + ? Elem[1] + : buildVector32({Elem.data()+Num/2, Num/2}, dl, HalfTy, DAG); + return DAG.getNode(HexagonISD::COMBINE, dl, VecTy, {H, L}); } SDValue -HexagonTargetLowering::LowerCONCAT_VECTORS(SDValue Op, - SelectionDAG &DAG) const { - SDLoc dl(Op); - bool UseHVX = Subtarget.useHVXOps(); - EVT VT = Op.getValueType(); - unsigned NElts = Op.getNumOperands(); - SDValue Vec0 = Op.getOperand(0); - EVT VecVT = Vec0.getValueType(); - unsigned Width = VecVT.getSizeInBits(); - - if (NElts == 2) { - MVT ST = VecVT.getSimpleVT(); - // We are trying to concat two v2i16 to a single v4i16, or two v4i8 - // into a single v8i8. - if (ST == MVT::v2i16 || ST == MVT::v4i8) - return DAG.getNode(HexagonISD::COMBINE, dl, VT, Op.getOperand(1), Vec0); +HexagonTargetLowering::extractVector(SDValue VecV, SDValue IdxV, + const SDLoc &dl, MVT ValTy, MVT ResTy, + SelectionDAG &DAG) const { + MVT VecTy = ty(VecV); + assert(!ValTy.isVector() || + VecTy.getVectorElementType() == ValTy.getVectorElementType()); + unsigned VecWidth = VecTy.getSizeInBits(); + unsigned ValWidth = ValTy.getSizeInBits(); + unsigned ElemWidth = VecTy.getVectorElementType().getSizeInBits(); + assert(VecWidth == 32 || VecWidth == 64); + assert((VecWidth % ElemWidth) == 0); - if (UseHVX) { - assert((Width == 64*8 && Subtarget.useHVXSglOps()) || - (Width == 128*8 && Subtarget.useHVXDblOps())); - SDValue Vec1 = Op.getOperand(1); - MVT OpTy = Subtarget.useHVXSglOps() ? MVT::v16i32 : MVT::v32i32; - MVT ReTy = Subtarget.useHVXSglOps() ? MVT::v32i32 : MVT::v64i32; - SDValue B0 = DAG.getNode(ISD::BITCAST, dl, OpTy, Vec0); - SDValue B1 = DAG.getNode(ISD::BITCAST, dl, OpTy, Vec1); - SDValue VC = DAG.getNode(HexagonISD::VCOMBINE, dl, ReTy, B1, B0); - return DAG.getNode(ISD::BITCAST, dl, VT, VC); - } - } + // Cast everything to scalar integer types. + MVT ScalarTy = tyScalar(VecTy); + VecV = DAG.getBitcast(ScalarTy, VecV); - if (VT.getSizeInBits() != 32 && VT.getSizeInBits() != 64) - return SDValue(); + SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32); + SDValue ExtV; - SDValue C0 = DAG.getConstant(0, dl, MVT::i64); - SDValue C32 = DAG.getConstant(32, dl, MVT::i64); - SDValue W = DAG.getConstant(Width, dl, MVT::i64); - // Create the "width" part of the argument to insert_rp/insertp_rp. - SDValue S = DAG.getNode(ISD::SHL, dl, MVT::i64, W, C32); - SDValue V = C0; - - for (unsigned i = 0, e = NElts; i != e; ++i) { - unsigned N = NElts-i-1; - SDValue OpN = Op.getOperand(N); - - if (VT.getSizeInBits() == 64 && OpN.getValueSizeInBits() == 32) { - SDValue C = DAG.getConstant(0, dl, MVT::i32); - OpN = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, OpN); + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) { + unsigned Off = C->getZExtValue() * ElemWidth; + if (VecWidth == 64 && ValWidth == 32) { + assert(Off == 0 || Off == 32); + unsigned SubIdx = Off == 0 ? Hexagon::isub_lo : Hexagon::isub_hi; + ExtV = DAG.getTargetExtractSubreg(SubIdx, dl, MVT::i32, VecV); + } else if (Off == 0 && (ValWidth % 8) == 0) { + ExtV = DAG.getZeroExtendInReg(VecV, dl, tyScalar(ValTy)); + } else { + SDValue OffV = DAG.getConstant(Off, dl, MVT::i32); + // The return type of EXTRACTU must be the same as the type of the + // input vector. + ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy, + {VecV, WidthV, OffV}); } - SDValue Idx = DAG.getConstant(N, dl, MVT::i64); - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i64, Idx, W); - SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i64, S, Offset); - if (VT.getSizeInBits() == 32) - V = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, {V, OpN, Or}); - else if (VT.getSizeInBits() == 64) - V = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, {V, OpN, Or}); - else - return SDValue(); + } else { + if (ty(IdxV) != MVT::i32) + IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32); + SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, + DAG.getConstant(ElemWidth, dl, MVT::i32)); + // EXTRACTURP takes width/offset in a 64-bit pair. + SDValue CombV = DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, + {WidthV, OffV}); + ExtV = DAG.getNode(HexagonISD::EXTRACTURP, dl, ScalarTy, + {VecV, CombV}); } - return DAG.getNode(ISD::BITCAST, dl, VT, V); + // Cast ExtV to the requested result type. + ExtV = DAG.getZExtOrTrunc(ExtV, dl, tyScalar(ResTy)); + ExtV = DAG.getBitcast(ResTy, ExtV); + return ExtV; } SDValue -HexagonTargetLowering::LowerEXTRACT_SUBVECTOR_HVX(SDValue Op, - SelectionDAG &DAG) const { - EVT VT = Op.getOperand(0).getValueType(); - SDLoc dl(Op); - bool UseHVX = Subtarget.useHVXOps(); - bool UseHVXSgl = Subtarget.useHVXSglOps(); - // Just in case... +HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV, + const SDLoc &dl, MVT ValTy, + SelectionDAG &DAG) const { + MVT VecTy = ty(VecV); + unsigned VecWidth = VecTy.getSizeInBits(); + unsigned ValWidth = ValTy.getSizeInBits(); + assert(VecWidth == 32 || VecWidth == 64); + assert((VecWidth % ValWidth) == 0); - if (!VT.isVector() || !UseHVX) - return SDValue(); + // Cast everything to scalar integer types. + MVT ScalarTy = MVT::getIntegerVT(VecWidth); + // The actual type of ValV may be different than ValTy (which is related + // to the vector type). + unsigned VW = ty(ValV).getSizeInBits(); + ValV = DAG.getBitcast(MVT::getIntegerVT(VW), ValV); + VecV = DAG.getBitcast(ScalarTy, VecV); + if (VW != VecWidth) + ValV = DAG.getAnyExtOrTrunc(ValV, dl, ScalarTy); - EVT ResVT = Op.getValueType(); - unsigned ResSize = ResVT.getSizeInBits(); - unsigned VectorSizeInBits = UseHVXSgl ? (64 * 8) : (128 * 8); - unsigned OpSize = VT.getSizeInBits(); + SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32); + SDValue InsV; - // We deal only with cases where the result is the vector size - // and the vector operand is a double register. - if (!(ResVT.isByteSized() && ResSize == VectorSizeInBits) || - !(VT.isByteSized() && OpSize == 2 * VectorSizeInBits)) - return SDValue(); + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) { + unsigned W = C->getZExtValue() * ValWidth; + SDValue OffV = DAG.getConstant(W, dl, MVT::i32); + InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy, + {VecV, ValV, WidthV, OffV}); + } else { + if (ty(IdxV) != MVT::i32) + IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32); + SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, WidthV); + // INSERTRP takes width/offset in a 64-bit pair. + SDValue CombV = DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, + {WidthV, OffV}); + InsV = DAG.getNode(HexagonISD::INSERTRP, dl, ScalarTy, + {VecV, ValV, CombV}); + } - ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Op.getOperand(1)); - if (!Cst) - return SDValue(); - unsigned Val = Cst->getZExtValue(); + return DAG.getNode(ISD::BITCAST, dl, VecTy, InsV); +} - // These two will get lowered to an appropriate EXTRACT_SUBREG in ISel. - if (Val == 0) { - SDValue Vec = Op.getOperand(0); - return DAG.getTargetExtractSubreg(Hexagon::vsub_lo, dl, ResVT, Vec); +SDValue +HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { + MVT VecTy = ty(Op); + unsigned BW = VecTy.getSizeInBits(); + if (BW == 32 || BW == 64) { + SmallVector<SDValue,8> Ops; + for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) + Ops.push_back(Op.getOperand(i)); + if (BW == 32) + return buildVector32(Ops, SDLoc(Op), VecTy, DAG); + return buildVector64(Ops, SDLoc(Op), VecTy, DAG); } - if (ResVT.getVectorNumElements() == Val) { - SDValue Vec = Op.getOperand(0); - return DAG.getTargetExtractSubreg(Hexagon::vsub_hi, dl, ResVT, Vec); - } + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) + return LowerHvxBuildVector(Op, DAG); return SDValue(); } SDValue -HexagonTargetLowering::LowerEXTRACT_VECTOR(SDValue Op, +HexagonTargetLowering::LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const { - // If we are dealing with EXTRACT_SUBVECTOR on a HVX type, we may - // be able to simplify it to an EXTRACT_SUBREG. - if (Op.getOpcode() == ISD::EXTRACT_SUBVECTOR && Subtarget.useHVXOps() && - isHvxVectorType(Op.getValueType().getSimpleVT())) - return LowerEXTRACT_SUBVECTOR_HVX(Op, DAG); - - EVT VT = Op.getValueType(); - int VTN = VT.isVector() ? VT.getVectorNumElements() : 1; - SDLoc dl(Op); - SDValue Idx = Op.getOperand(1); - SDValue Vec = Op.getOperand(0); - EVT VecVT = Vec.getValueType(); - EVT EltVT = VecVT.getVectorElementType(); - int EltSize = EltVT.getSizeInBits(); - SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT ? - EltSize : VTN * EltSize, dl, MVT::i64); - - // Constant element number. - if (ConstantSDNode *CI = dyn_cast<ConstantSDNode>(Idx)) { - uint64_t X = CI->getZExtValue(); - SDValue Offset = DAG.getConstant(X * EltSize, dl, MVT::i32); - const SDValue Ops[] = {Vec, Width, Offset}; - - ConstantSDNode *CW = dyn_cast<ConstantSDNode>(Width); - assert(CW && "Non constant width in LowerEXTRACT_VECTOR"); - - SDValue N; - MVT SVT = VecVT.getSimpleVT(); - uint64_t W = CW->getZExtValue(); - - if (W == 32) { - // Translate this node into EXTRACT_SUBREG. - unsigned Subreg = (X == 0) ? Hexagon::isub_lo : 0; - - if (X == 0) - Subreg = Hexagon::isub_lo; - else if (SVT == MVT::v2i32 && X == 1) - Subreg = Hexagon::isub_hi; - else if (SVT == MVT::v4i16 && X == 2) - Subreg = Hexagon::isub_hi; - else if (SVT == MVT::v8i8 && X == 4) - Subreg = Hexagon::isub_hi; - else - llvm_unreachable("Bad offset"); - N = DAG.getTargetExtractSubreg(Subreg, dl, MVT::i32, Vec); - - } else if (SVT.getSizeInBits() == 32) { - N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i32, Ops); - } else if (SVT.getSizeInBits() == 64) { - N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i64, Ops); - if (VT.getSizeInBits() == 32) - N = DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, N); - } else - return SDValue(); + MVT VecTy = ty(Op); + assert(!Subtarget.useHVXOps() || !Subtarget.isHVXVectorType(VecTy)); - return DAG.getNode(ISD::BITCAST, dl, VT, N); + if (VecTy.getSizeInBits() == 64) { + assert(Op.getNumOperands() == 2); + return DAG.getNode(HexagonISD::COMBINE, SDLoc(Op), VecTy, Op.getOperand(1), + Op.getOperand(0)); } - // Variable element number. - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx, - DAG.getConstant(EltSize, dl, MVT::i32)); - SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width, - DAG.getConstant(32, dl, MVT::i64)); - SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset); - - const SDValue Ops[] = {Vec, Combined}; - - SDValue N; - if (VecVT.getSizeInBits() == 32) { - N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i32, Ops); - } else { - N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i64, Ops); - if (VT.getSizeInBits() == 32) - N = DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, N); - } - return DAG.getNode(ISD::BITCAST, dl, VT, N); + return SDValue(); } SDValue -HexagonTargetLowering::LowerINSERT_VECTOR(SDValue Op, - SelectionDAG &DAG) const { - EVT VT = Op.getValueType(); - int VTN = VT.isVector() ? VT.getVectorNumElements() : 1; - SDLoc dl(Op); +HexagonTargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op, + SelectionDAG &DAG) const { SDValue Vec = Op.getOperand(0); - SDValue Val = Op.getOperand(1); - SDValue Idx = Op.getOperand(2); - EVT VecVT = Vec.getValueType(); - EVT EltVT = VecVT.getVectorElementType(); - int EltSize = EltVT.getSizeInBits(); - SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::INSERT_VECTOR_ELT ? - EltSize : VTN * EltSize, dl, MVT::i64); + MVT VecTy = ty(Vec); + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) + return LowerHvxExtractElement(Op, DAG); - if (ConstantSDNode *C = cast<ConstantSDNode>(Idx)) { - SDValue Offset = DAG.getConstant(C->getSExtValue() * EltSize, dl, MVT::i32); - const SDValue Ops[] = {Vec, Val, Width, Offset}; - - SDValue N; - if (VT.getSizeInBits() == 32) - N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, Ops); - else if (VT.getSizeInBits() == 64) - N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, Ops); - else - return SDValue(); + MVT ElemTy = ty(Vec).getVectorElementType(); + return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG); +} - return DAG.getNode(ISD::BITCAST, dl, VT, N); - } +SDValue +HexagonTargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op, + SelectionDAG &DAG) const { + SDValue Vec = Op.getOperand(0); + MVT VecTy = ty(Vec); + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) + return LowerHvxExtractSubvector(Op, DAG); - // Variable element number. - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx, - DAG.getConstant(EltSize, dl, MVT::i32)); - SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width, - DAG.getConstant(32, dl, MVT::i64)); - SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset); + return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ty(Op), ty(Op), DAG); +} - if (VT.getSizeInBits() == 64 && Val.getValueSizeInBits() == 32) { - SDValue C = DAG.getConstant(0, dl, MVT::i32); - Val = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, Val); - } +SDValue +HexagonTargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, + SelectionDAG &DAG) const { + MVT VecTy = ty(Op); + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) + return LowerHvxInsertElement(Op, DAG); - const SDValue Ops[] = {Vec, Val, Combined}; + return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2), + SDLoc(Op), VecTy.getVectorElementType(), DAG); +} - SDValue N; - if (VT.getSizeInBits() == 32) - N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, Ops); - else if (VT.getSizeInBits() == 64) - N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, Ops); - else - return SDValue(); +SDValue +HexagonTargetLowering::LowerINSERT_SUBVECTOR(SDValue Op, + SelectionDAG &DAG) const { + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(ty(Op))) + return LowerHvxInsertSubvector(Op, DAG); - return DAG.getNode(ISD::BITCAST, dl, VT, N); + SDValue ValV = Op.getOperand(1); + return insertVector(Op.getOperand(0), ValV, Op.getOperand(2), + SDLoc(Op), ty(ValV), DAG); } bool @@ -2870,10 +2826,10 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { #endif llvm_unreachable("Should not custom lower this!"); case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); - case ISD::INSERT_SUBVECTOR: return LowerINSERT_VECTOR(Op, DAG); - case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR(Op, DAG); - case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_VECTOR(Op, DAG); - case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR(Op, DAG); + case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); + case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); case ISD::SRA: @@ -2899,7 +2855,12 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::INLINEASM: return LowerINLINEASM(Op, DAG); case ISD::PREFETCH: return LowerPREFETCH(Op, DAG); case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG); + case ISD::MUL: + if (Subtarget.useHVXOps()) + return LowerHvxMul(Op, DAG); + break; } + return SDValue(); } /// Returns relocation base for the given PIC jumptable. @@ -2923,7 +2884,11 @@ HexagonTargetLowering::getConstraintType(StringRef Constraint) const { case 'q': case 'v': if (Subtarget.useHVXOps()) - return C_Register; + return C_RegisterClass; + break; + case 'a': + return C_RegisterClass; + default: break; } } @@ -2933,49 +2898,53 @@ HexagonTargetLowering::getConstraintType(StringRef Constraint) const { std::pair<unsigned, const TargetRegisterClass*> HexagonTargetLowering::getRegForInlineAsmConstraint( const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const { - bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps(); if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': // R0-R31 switch (VT.SimpleTy) { default: - llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type"); + return {0u, nullptr}; case MVT::i1: case MVT::i8: case MVT::i16: case MVT::i32: case MVT::f32: - return std::make_pair(0U, &Hexagon::IntRegsRegClass); + return {0u, &Hexagon::IntRegsRegClass}; case MVT::i64: case MVT::f64: - return std::make_pair(0U, &Hexagon::DoubleRegsRegClass); + return {0u, &Hexagon::DoubleRegsRegClass}; } + break; + case 'a': // M0-M1 + if (VT != MVT::i32) + return {0u, nullptr}; + return {0u, &Hexagon::ModRegsRegClass}; case 'q': // q0-q3 switch (VT.getSizeInBits()) { default: - llvm_unreachable("getRegForInlineAsmConstraint Unhandled vector size"); + return {0u, nullptr}; case 512: - return std::make_pair(0U, &Hexagon::VecPredRegsRegClass); case 1024: - return std::make_pair(0U, &Hexagon::VecPredRegs128BRegClass); + return {0u, &Hexagon::HvxQRRegClass}; } + break; case 'v': // V0-V31 switch (VT.getSizeInBits()) { default: - llvm_unreachable("getRegForInlineAsmConstraint Unhandled vector size"); + return {0u, nullptr}; case 512: - return std::make_pair(0U, &Hexagon::VectorRegsRegClass); + return {0u, &Hexagon::HvxVRRegClass}; case 1024: - if (Subtarget.hasV60TOps() && UseHVX && UseHVXDbl) - return std::make_pair(0U, &Hexagon::VectorRegs128BRegClass); - return std::make_pair(0U, &Hexagon::VecDblRegsRegClass); + if (Subtarget.hasV60TOps() && Subtarget.useHVX128BOps()) + return {0u, &Hexagon::HvxVRRegClass}; + return {0u, &Hexagon::HvxWRRegClass}; case 2048: - return std::make_pair(0U, &Hexagon::VecDblRegs128BRegClass); + return {0u, &Hexagon::HvxWRRegClass}; } - + break; default: - llvm_unreachable("Unknown asm register class"); + return {0u, nullptr}; } } @@ -2993,7 +2962,7 @@ bool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { /// AM is legal for this target, for a load/store of the specified type. bool HexagonTargetLowering::isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, - unsigned AS) const { + unsigned AS, Instruction *I) const { if (Ty->isSized()) { // When LSR detects uses of the same base address to access different // types (e.g. unions), it will assume a conservative type for these @@ -3055,8 +3024,8 @@ bool HexagonTargetLowering::IsEligibleForTailCallOptimization( const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG& DAG) const { - const Function *CallerF = DAG.getMachineFunction().getFunction(); - CallingConv::ID CallerCC = CallerF->getCallingConv(); + const Function &CallerF = DAG.getMachineFunction().getFunction(); + CallingConv::ID CallerCC = CallerF.getCallingConv(); bool CCMatch = CallerCC == CalleeCC; // *************************************************************************** @@ -3142,9 +3111,6 @@ bool HexagonTargetLowering::allowsMisalignedMemoryAccesses(EVT VT, case MVT::v16i32: case MVT::v32i32: case MVT::v64i32: - case MVT::v8i64: - case MVT::v16i64: - case MVT::v32i64: return true; } return false; @@ -3162,24 +3128,21 @@ HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI, case MVT::v64i8: case MVT::v32i16: case MVT::v16i32: - case MVT::v8i64: - RRC = &Hexagon::VectorRegsRegClass; + RRC = &Hexagon::HvxVRRegClass; break; case MVT::v128i8: case MVT::v64i16: case MVT::v32i32: - case MVT::v16i64: if (Subtarget.hasV60TOps() && Subtarget.useHVXOps() && - Subtarget.useHVXDblOps()) - RRC = &Hexagon::VectorRegs128BRegClass; + Subtarget.useHVX128BOps()) + RRC = &Hexagon::HvxVRRegClass; else - RRC = &Hexagon::VecDblRegsRegClass; + RRC = &Hexagon::HvxWRRegClass; break; case MVT::v256i8: case MVT::v128i16: case MVT::v64i32: - case MVT::v32i64: - RRC = &Hexagon::VecDblRegs128BRegClass; + RRC = &Hexagon::HvxWRRegClass; break; } return std::make_pair(RRC, Cost); |
