aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelLowering.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.cpp330
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;
}