diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLowering.cpp | 330 |
1 files changed, 241 insertions, 89 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index e11ecdc7d035..768fea639cf9 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -109,6 +109,11 @@ static cl::opt<bool> AlignLoads("hexagon-align-loads", cl::Hidden, cl::init(false), cl::desc("Rewrite unaligned loads as a pair of aligned loads")); +static cl::opt<bool> + DisableArgsMinAlignment("hexagon-disable-args-min-alignment", cl::Hidden, + cl::init(false), + cl::desc("Disable minimum alignment of 1 for " + "arguments passed by value on stack")); namespace { @@ -167,10 +172,10 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl) { SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32); - return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), - /*isVolatile=*/false, /*AlwaysInline=*/false, - /*isTailCall=*/false, - MachinePointerInfo(), MachinePointerInfo()); + return DAG.getMemcpy( + Chain, dl, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(), + /*isVolatile=*/false, /*AlwaysInline=*/false, + /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); } bool @@ -387,19 +392,22 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFrameInfo &MFI = MF.getFrameInfo(); auto PtrVT = getPointerTy(MF.getDataLayout()); - unsigned NumParams = CLI.CS.getInstruction() - ? CLI.CS.getFunctionType()->getNumParams() - : 0; + unsigned NumParams = CLI.CB ? CLI.CB->getFunctionType()->getNumParams() : 0; if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(GAN->getGlobal(), dl, MVT::i32); + // Linux ABI treats var-arg calls the same way as regular ones. + bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg; + // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; - HexagonCCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext(), + HexagonCCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext(), NumParams); if (Subtarget.useHVXOps()) CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_HVX); + else if (DisableArgsMinAlignment) + CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_Legacy); else CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon); @@ -429,7 +437,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT); bool NeedsArgAlign = false; - unsigned LargestAlignSeen = 0; + Align LargestAlignSeen; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -466,8 +474,8 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, StackPtr.getValueType()); MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr); if (ArgAlign) - LargestAlignSeen = std::max(LargestAlignSeen, - (unsigned)VA.getLocVT().getStoreSizeInBits() >> 3); + LargestAlignSeen = std::max( + LargestAlignSeen, Align(VA.getLocVT().getStoreSizeInBits() / 8)); if (Flags.isByVal()) { // The argument is a struct passed by value. According to LLVM, "Arg" // is a pointer. @@ -490,7 +498,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, if (NeedsArgAlign && Subtarget.hasV60Ops()) { LLVM_DEBUG(dbgs() << "Function needs byte stack align due to call args\n"); - unsigned VecAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass); + Align VecAlign(HRI.getSpillAlignment(Hexagon::HvxVRRegClass)); LargestAlignSeen = std::max(LargestAlignSeen, VecAlign); MFI.ensureMaxAlignment(LargestAlignSeen); } @@ -726,7 +734,7 @@ HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, auto &HFI = *Subtarget.getFrameLowering(); // "Zero" means natural stack alignment. if (A == 0) - A = HFI.getStackAlignment(); + A = HFI.getStackAlign().value(); LLVM_DEBUG({ dbgs () << __func__ << " Align: " << A << " Size: "; @@ -750,13 +758,19 @@ SDValue HexagonTargetLowering::LowerFormalArguments( MachineFrameInfo &MFI = MF.getFrameInfo(); MachineRegisterInfo &MRI = MF.getRegInfo(); + // Linux ABI treats var-arg calls the same way as regular ones. + bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg; + // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; - HexagonCCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext(), + HexagonCCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, + *DAG.getContext(), MF.getFunction().getFunctionType()->getNumParams()); if (Subtarget.useHVXOps()) CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_HVX); + else if (DisableArgsMinAlignment) + CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_Legacy); else CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon); @@ -766,8 +780,24 @@ SDValue HexagonTargetLowering::LowerFormalArguments( // caller's stack is passed only when the struct size is smaller than (and // equal to) 8 bytes. If not, no address will be passed into callee and // callee return the result direclty through R0/R1. + auto NextSingleReg = [] (const TargetRegisterClass &RC, unsigned Reg) { + switch (RC.getID()) { + case Hexagon::IntRegsRegClassID: + return Reg - Hexagon::R0 + 1; + case Hexagon::DoubleRegsRegClassID: + return (Reg - Hexagon::D0 + 1) * 2; + case Hexagon::HvxVRRegClassID: + return Reg - Hexagon::V0 + 1; + case Hexagon::HvxWRRegClassID: + return (Reg - Hexagon::W0 + 1) * 2; + } + llvm_unreachable("Unexpected register class"); + }; + auto &HFL = const_cast<HexagonFrameLowering&>(*Subtarget.getFrameLowering()); auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>(); + HFL.FirstVarArgSavedReg = 0; + HMFI.setFirstNamedArgFrameIndex(-int(MFI.getNumFixedObjects())); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -811,6 +841,7 @@ SDValue HexagonTargetLowering::LowerFormalArguments( } InVals.push_back(Copy); MRI.addLiveIn(VA.getLocReg(), VReg); + HFL.FirstVarArgSavedReg = NextSingleReg(*RC, VA.getLocReg()); } else { assert(VA.isMemLoc() && "Argument should be passed in memory"); @@ -838,8 +869,48 @@ SDValue HexagonTargetLowering::LowerFormalArguments( } } + if (IsVarArg && Subtarget.isEnvironmentMusl()) { + for (int i = HFL.FirstVarArgSavedReg; i < 6; i++) + MRI.addLiveIn(Hexagon::R0+i); + } + + if (IsVarArg && Subtarget.isEnvironmentMusl()) { + HMFI.setFirstNamedArgFrameIndex(HMFI.getFirstNamedArgFrameIndex() - 1); + HMFI.setLastNamedArgFrameIndex(-int(MFI.getNumFixedObjects())); + + // Create Frame index for the start of register saved area. + int NumVarArgRegs = 6 - HFL.FirstVarArgSavedReg; + bool RequiresPadding = (NumVarArgRegs & 1); + int RegSaveAreaSizePlusPadding = RequiresPadding + ? (NumVarArgRegs + 1) * 4 + : NumVarArgRegs * 4; + + if (RegSaveAreaSizePlusPadding > 0) { + // The offset to saved register area should be 8 byte aligned. + int RegAreaStart = HEXAGON_LRFP_SIZE + CCInfo.getNextStackOffset(); + if (!(RegAreaStart % 8)) + RegAreaStart = (RegAreaStart + 7) & -8; - if (IsVarArg) { + int RegSaveAreaFrameIndex = + MFI.CreateFixedObject(RegSaveAreaSizePlusPadding, RegAreaStart, true); + HMFI.setRegSavedAreaStartFrameIndex(RegSaveAreaFrameIndex); + + // This will point to the next argument passed via stack. + int Offset = RegAreaStart + RegSaveAreaSizePlusPadding; + int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true); + HMFI.setVarArgsFrameIndex(FI); + } else { + // This will point to the next argument passed via stack, when + // there is no saved register area. + int Offset = HEXAGON_LRFP_SIZE + CCInfo.getNextStackOffset(); + int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true); + HMFI.setRegSavedAreaStartFrameIndex(FI); + HMFI.setVarArgsFrameIndex(FI); + } + } + + + if (IsVarArg && !Subtarget.isEnvironmentMusl()) { // This will point to the next argument passed via stack. int Offset = HEXAGON_LRFP_SIZE + CCInfo.getNextStackOffset(); int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true); @@ -857,8 +928,81 @@ HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>(); SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, Op.getOperand(1), - MachinePointerInfo(SV)); + + if (!Subtarget.isEnvironmentMusl()) { + return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, Op.getOperand(1), + MachinePointerInfo(SV)); + } + auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>(); + auto &HFL = *Subtarget.getFrameLowering(); + SDLoc DL(Op); + SmallVector<SDValue, 8> MemOps; + + // Get frame index of va_list. + SDValue FIN = Op.getOperand(1); + + // If first Vararg register is odd, add 4 bytes to start of + // saved register area to point to the first register location. + // This is because the saved register area has to be 8 byte aligned. + // Incase of an odd start register, there will be 4 bytes of padding in + // the beginning of saved register area. If all registers area used up, + // the following condition will handle it correctly. + SDValue SavedRegAreaStartFrameIndex = + DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), MVT::i32); + + auto PtrVT = getPointerTy(DAG.getDataLayout()); + + if (HFL.FirstVarArgSavedReg & 1) + SavedRegAreaStartFrameIndex = + DAG.getNode(ISD::ADD, DL, PtrVT, + DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), + MVT::i32), + DAG.getIntPtrConstant(4, DL)); + + // Store the saved register area start pointer. + SDValue Store = + DAG.getStore(Op.getOperand(0), DL, + SavedRegAreaStartFrameIndex, + FIN, MachinePointerInfo(SV)); + MemOps.push_back(Store); + + // Store saved register area end pointer. + FIN = DAG.getNode(ISD::ADD, DL, PtrVT, + FIN, DAG.getIntPtrConstant(4, DL)); + Store = DAG.getStore(Op.getOperand(0), DL, + DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(), + PtrVT), + FIN, MachinePointerInfo(SV, 4)); + MemOps.push_back(Store); + + // Store overflow area pointer. + FIN = DAG.getNode(ISD::ADD, DL, PtrVT, + FIN, DAG.getIntPtrConstant(4, DL)); + Store = DAG.getStore(Op.getOperand(0), DL, + DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(), + PtrVT), + FIN, MachinePointerInfo(SV, 8)); + MemOps.push_back(Store); + + return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps); +} + +SDValue +HexagonTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) const { + // Assert that the linux ABI is enabled for the current compilation. + assert(Subtarget.isEnvironmentMusl() && "Linux ABI should be enabled"); + SDValue Chain = Op.getOperand(0); + SDValue DestPtr = Op.getOperand(1); + SDValue SrcPtr = Op.getOperand(2); + const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue(); + const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); + SDLoc DL(Op); + // Size of the va_list is 12 bytes as it has 3 pointers. Therefore, + // we need to memcopy 12 bytes from va_list to another similar list. + return DAG.getMemcpy(Chain, DL, DestPtr, SrcPtr, + DAG.getIntPtrConstant(12, DL), Align(4), + /*isVolatile*/ false, false, false, + MachinePointerInfo(DestSV), MachinePointerInfo(SrcSV)); } SDValue HexagonTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { @@ -943,57 +1087,40 @@ 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); + if (auto *CV = dyn_cast<ConstantVector>(CPN->getConstVal())) { + if (cast<VectorType>(CV->getType())->getElementType()->isIntegerTy(1)) { + IRBuilder<> IRB(CV->getContext()); + SmallVector<Constant*, 128> NewConst; + unsigned VecLen = CV->getNumOperands(); + assert(isPowerOf2_32(VecLen) && + "conversion only supported for pow2 VectorSize"); + for (unsigned i = 0; i < VecLen; ++i) + NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue())); + + CVal = ConstantVector::get(NewConst); + isVTi1Type = true; } } - unsigned Align = CPN->getAlignment(); + Align Alignment = CPN->getAlign(); bool IsPositionIndependent = isPositionIndependent(); unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0; unsigned Offset = 0; SDValue T; if (CPN->isMachineConstantPoolEntry()) - T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Align, Offset, - TF); + T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Alignment, + Offset, TF); else if (isVTi1Type) - T = DAG.getTargetConstantPool(CVal, ValTy, Align, Offset, TF); + T = DAG.getTargetConstantPool(CVal, ValTy, Alignment, Offset, TF); else - T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Align, Offset, TF); + T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Alignment, Offset, + TF); assert(cast<ConstantPoolSDNode>(T)->getTargetFlags() == TF && "Inconsistent target flag encountered"); @@ -1375,7 +1502,10 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::VASTART, MVT::Other, Custom); setOperationAction(ISD::VAEND, MVT::Other, Expand); setOperationAction(ISD::VAARG, MVT::Other, Expand); - setOperationAction(ISD::VACOPY, MVT::Other, Expand); + if (Subtarget.isEnvironmentMusl()) + setOperationAction(ISD::VACOPY, MVT::Other, Custom); + else + setOperationAction(ISD::VACOPY, MVT::Other, Expand); setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); @@ -1621,6 +1751,11 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FADD, MVT::f64, Legal); setOperationAction(ISD::FSUB, MVT::f64, Legal); } + if (Subtarget.hasV67Ops()) { + setOperationAction(ISD::FMINNUM, MVT::f64, Legal); + setOperationAction(ISD::FMAXNUM, MVT::f64, Legal); + setOperationAction(ISD::FMUL, MVT::f64, Legal); + } setTargetDAGCombine(ISD::VSELECT); @@ -1855,8 +1990,7 @@ bool HexagonTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, // The offset value comes through Modifier register. For now, assume the // offset is 0. Info.offset = 0; - Info.align = - MaybeAlign(DL.getABITypeAlignment(Info.memVT.getTypeForEVT(Cont))); + Info.align = DL.getABITypeAlign(Info.memVT.getTypeForEVT(Cont)); Info.flags = MachineMemOperand::MOLoad; return true; } @@ -2139,13 +2273,16 @@ HexagonTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const { const SDLoc &dl(Op); // Handle conversion from i8 to v8i1. - if (ResTy == MVT::v8i1) { - SDValue Sc = DAG.getBitcast(tyScalar(InpTy), InpV); - SDValue Ext = DAG.getZExtOrTrunc(Sc, dl, MVT::i32); - return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG); + if (InpTy == MVT::i8) { + if (ResTy == MVT::v8i1) { + SDValue Sc = DAG.getBitcast(tyScalar(InpTy), InpV); + SDValue Ext = DAG.getZExtOrTrunc(Sc, dl, MVT::i32); + return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG); + } + return SDValue(); } - return SDValue(); + return Op; } bool @@ -2779,10 +2916,10 @@ HexagonTargetLowering::LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) MachineMemOperand *WideMMO = nullptr; if (MachineMemOperand *MMO = LN->getMemOperand()) { MachineFunction &MF = DAG.getMachineFunction(); - WideMMO = MF.getMachineMemOperand(MMO->getPointerInfo(), MMO->getFlags(), - 2*LoadLen, LoadLen, MMO->getAAInfo(), MMO->getRanges(), - MMO->getSyncScopeID(), MMO->getOrdering(), - MMO->getFailureOrdering()); + WideMMO = MF.getMachineMemOperand( + MMO->getPointerInfo(), MMO->getFlags(), 2 * LoadLen, Align(LoadLen), + MMO->getAAInfo(), MMO->getRanges(), MMO->getSyncScopeID(), + MMO->getOrdering(), MMO->getFailureOrdering()); } SDValue Load0 = DAG.getLoad(LoadTy, dl, Chain, Base0, WideMMO); @@ -2928,6 +3065,7 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG); + case ISD::VACOPY: return LowerVACOPY(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); @@ -2946,6 +3084,12 @@ void HexagonTargetLowering::LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { + if (isHvxOperation(N)) { + LowerHvxOperationWrapper(N, Results, DAG); + if (!Results.empty()) + return; + } + // We are only custom-lowering stores to verify the alignment of the // address if it is a compile-time constant. Since a store can be modified // during type-legalization (the value being stored may need legalization), @@ -2959,6 +3103,12 @@ void HexagonTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { + if (isHvxOperation(N)) { + ReplaceHvxNodeResults(N, Results, DAG); + if (!Results.empty()) + return; + } + const SDLoc &dl(N); switch (N->getOpcode()) { case ISD::SRL: @@ -3079,8 +3229,8 @@ HexagonTargetLowering::getRegForInlineAsmConstraint( switch (VT.getSizeInBits()) { default: return {0u, nullptr}; - case 512: - case 1024: + case 64: + case 128: return {0u, &Hexagon::HvxQRRegClass}; } break; @@ -3127,12 +3277,12 @@ bool HexagonTargetLowering::isLegalAddressingMode(const DataLayout &DL, // The type Ty passed here would then be "void". Skip the alignment // checks, but do not return false right away, since that confuses // LSR into crashing. - unsigned A = DL.getABITypeAlignment(Ty); + Align A = DL.getABITypeAlign(Ty); // The base offset must be a multiple of the alignment. - if ((AM.BaseOffs % A) != 0) + if (!isAligned(A, AM.BaseOffs)) return false; // The shifted offset must fit in 11 bits. - if (!isInt<11>(AM.BaseOffs >> Log2_32(A))) + if (!isInt<11>(AM.BaseOffs >> Log2(A))) return false; } @@ -3232,30 +3382,36 @@ bool HexagonTargetLowering::IsEligibleForTailCallOptimization( /// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it /// does not need to be loaded. It returns EVT::Other if the type should be /// determined using generic target-independent logic. -EVT HexagonTargetLowering::getOptimalMemOpType(uint64_t Size, - unsigned DstAlign, unsigned SrcAlign, bool IsMemset, bool ZeroMemset, - bool MemcpyStrSrc, const AttributeList &FuncAttributes) const { - - auto Aligned = [](unsigned GivenA, unsigned MinA) -> bool { - return (GivenA % MinA) == 0; - }; - - if (Size >= 8 && Aligned(DstAlign, 8) && (IsMemset || Aligned(SrcAlign, 8))) +EVT HexagonTargetLowering::getOptimalMemOpType( + const MemOp &Op, const AttributeList &FuncAttributes) const { + if (Op.size() >= 8 && Op.isAligned(Align(8))) return MVT::i64; - if (Size >= 4 && Aligned(DstAlign, 4) && (IsMemset || Aligned(SrcAlign, 4))) + if (Op.size() >= 4 && Op.isAligned(Align(4))) return MVT::i32; - if (Size >= 2 && Aligned(DstAlign, 2) && (IsMemset || Aligned(SrcAlign, 2))) + if (Op.size() >= 2 && Op.isAligned(Align(2))) return MVT::i16; - return MVT::Other; } +bool HexagonTargetLowering::allowsMemoryAccess( + LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace, + Align Alignment, MachineMemOperand::Flags Flags, bool *Fast) const { + MVT SVT = VT.getSimpleVT(); + if (Subtarget.isHVXVectorType(SVT, true)) + return allowsHvxMemoryAccess(SVT, Flags, Fast); + return TargetLoweringBase::allowsMemoryAccess( + Context, DL, VT, AddrSpace, Alignment, Flags, Fast); +} + bool HexagonTargetLowering::allowsMisalignedMemoryAccesses( - EVT VT, unsigned AS, unsigned Align, MachineMemOperand::Flags Flags, - bool *Fast) const { + EVT VT, unsigned AddrSpace, unsigned Alignment, + MachineMemOperand::Flags Flags, bool *Fast) const { + MVT SVT = VT.getSimpleVT(); + if (Subtarget.isHVXVectorType(SVT, true)) + return allowsHvxMisalignedMemoryAccesses(SVT, Flags, Fast); if (Fast) *Fast = false; - return Subtarget.isHVXVectorType(VT.getSimpleVT()); + return false; } std::pair<const TargetRegisterClass*, uint8_t> @@ -3357,9 +3513,5 @@ bool HexagonTargetLowering::shouldExpandAtomicStoreInIR(StoreInst *SI) const { TargetLowering::AtomicExpansionKind HexagonTargetLowering::shouldExpandAtomicCmpXchgInIR( AtomicCmpXchgInst *AI) const { - const DataLayout &DL = AI->getModule()->getDataLayout(); - unsigned Size = DL.getTypeStoreSize(AI->getCompareOperand()->getType()); - if (Size >= 4 && Size <= 8) - return AtomicExpansionKind::LLSC; - return AtomicExpansionKind::None; + return AtomicExpansionKind::LLSC; } |