mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Allow memory intrinsics to be tail calls
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234764 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
12a7039644
commit
fcc330abfe
@ -685,16 +685,16 @@ public:
|
|||||||
|
|
||||||
SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
||||||
SDValue Size, unsigned Align, bool isVol, bool AlwaysInline,
|
SDValue Size, unsigned Align, bool isVol, bool AlwaysInline,
|
||||||
MachinePointerInfo DstPtrInfo,
|
bool isTailCall, MachinePointerInfo DstPtrInfo,
|
||||||
MachinePointerInfo SrcPtrInfo);
|
MachinePointerInfo SrcPtrInfo);
|
||||||
|
|
||||||
SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
||||||
SDValue Size, unsigned Align, bool isVol,
|
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
|
||||||
MachinePointerInfo DstPtrInfo,
|
MachinePointerInfo DstPtrInfo,
|
||||||
MachinePointerInfo SrcPtrInfo);
|
MachinePointerInfo SrcPtrInfo);
|
||||||
|
|
||||||
SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src,
|
||||||
SDValue Size, unsigned Align, bool isVol,
|
SDValue Size, unsigned Align, bool isVol, bool isTailCall,
|
||||||
MachinePointerInfo DstPtrInfo);
|
MachinePointerInfo DstPtrInfo);
|
||||||
|
|
||||||
/// Helper function to make it easier to build SetCC's if you just
|
/// Helper function to make it easier to build SetCC's if you just
|
||||||
|
@ -4294,7 +4294,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, SDLoc dl,
|
|||||||
SDValue SelectionDAG::getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst,
|
SDValue SelectionDAG::getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst,
|
||||||
SDValue Src, SDValue Size,
|
SDValue Src, SDValue Size,
|
||||||
unsigned Align, bool isVol, bool AlwaysInline,
|
unsigned Align, bool isVol, bool AlwaysInline,
|
||||||
MachinePointerInfo DstPtrInfo,
|
bool isTailCall, MachinePointerInfo DstPtrInfo,
|
||||||
MachinePointerInfo SrcPtrInfo) {
|
MachinePointerInfo SrcPtrInfo) {
|
||||||
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
||||||
|
|
||||||
@ -4352,15 +4352,16 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst,
|
|||||||
Type::getVoidTy(*getContext()),
|
Type::getVoidTy(*getContext()),
|
||||||
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMCPY),
|
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMCPY),
|
||||||
TLI->getPointerTy()), std::move(Args), 0)
|
TLI->getPointerTy()), std::move(Args), 0)
|
||||||
.setDiscardResult();
|
.setDiscardResult()
|
||||||
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
.setTailCall(isTailCall);
|
||||||
|
|
||||||
|
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
||||||
return CallResult.second;
|
return CallResult.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue SelectionDAG::getMemmove(SDValue Chain, SDLoc dl, SDValue Dst,
|
SDValue SelectionDAG::getMemmove(SDValue Chain, SDLoc dl, SDValue Dst,
|
||||||
SDValue Src, SDValue Size,
|
SDValue Src, SDValue Size,
|
||||||
unsigned Align, bool isVol,
|
unsigned Align, bool isVol, bool isTailCall,
|
||||||
MachinePointerInfo DstPtrInfo,
|
MachinePointerInfo DstPtrInfo,
|
||||||
MachinePointerInfo SrcPtrInfo) {
|
MachinePointerInfo SrcPtrInfo) {
|
||||||
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
||||||
@ -4407,15 +4408,16 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, SDLoc dl, SDValue Dst,
|
|||||||
Type::getVoidTy(*getContext()),
|
Type::getVoidTy(*getContext()),
|
||||||
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMMOVE),
|
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMMOVE),
|
||||||
TLI->getPointerTy()), std::move(Args), 0)
|
TLI->getPointerTy()), std::move(Args), 0)
|
||||||
.setDiscardResult();
|
.setDiscardResult()
|
||||||
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
.setTailCall(isTailCall);
|
||||||
|
|
||||||
|
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
||||||
return CallResult.second;
|
return CallResult.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue SelectionDAG::getMemset(SDValue Chain, SDLoc dl, SDValue Dst,
|
SDValue SelectionDAG::getMemset(SDValue Chain, SDLoc dl, SDValue Dst,
|
||||||
SDValue Src, SDValue Size,
|
SDValue Src, SDValue Size,
|
||||||
unsigned Align, bool isVol,
|
unsigned Align, bool isVol, bool isTailCall,
|
||||||
MachinePointerInfo DstPtrInfo) {
|
MachinePointerInfo DstPtrInfo) {
|
||||||
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
assert(Align && "The SDAG layer expects explicit alignment and reserves 0");
|
||||||
|
|
||||||
@ -4464,7 +4466,8 @@ SDValue SelectionDAG::getMemset(SDValue Chain, SDLoc dl, SDValue Dst,
|
|||||||
Type::getVoidTy(*getContext()),
|
Type::getVoidTy(*getContext()),
|
||||||
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMSET),
|
getExternalSymbol(TLI->getLibcallName(RTLIB::MEMSET),
|
||||||
TLI->getPointerTy()), std::move(Args), 0)
|
TLI->getPointerTy()), std::move(Args), 0)
|
||||||
.setDiscardResult();
|
.setDiscardResult()
|
||||||
|
.setTailCall(isTailCall);
|
||||||
|
|
||||||
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
|
||||||
return CallResult.second;
|
return CallResult.second;
|
||||||
|
@ -4592,9 +4592,12 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
if (!Align)
|
if (!Align)
|
||||||
Align = 1; // @llvm.memcpy defines 0 and 1 to both mean no alignment.
|
Align = 1; // @llvm.memcpy defines 0 and 1 to both mean no alignment.
|
||||||
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
||||||
DAG.setRoot(DAG.getMemcpy(getRoot(), sdl, Op1, Op2, Op3, Align, isVol, false,
|
bool isTC = I.isTailCall() && isInTailCallPosition(&I, DAG.getTarget());
|
||||||
MachinePointerInfo(I.getArgOperand(0)),
|
SDValue MC = DAG.getMemcpy(getRoot(), sdl, Op1, Op2, Op3, Align, isVol,
|
||||||
MachinePointerInfo(I.getArgOperand(1))));
|
false, isTC,
|
||||||
|
MachinePointerInfo(I.getArgOperand(0)),
|
||||||
|
MachinePointerInfo(I.getArgOperand(1)));
|
||||||
|
updateDAGForMaybeTailCall(MC);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
case Intrinsic::memset: {
|
case Intrinsic::memset: {
|
||||||
@ -4611,8 +4614,10 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
if (!Align)
|
if (!Align)
|
||||||
Align = 1; // @llvm.memset defines 0 and 1 to both mean no alignment.
|
Align = 1; // @llvm.memset defines 0 and 1 to both mean no alignment.
|
||||||
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
||||||
DAG.setRoot(DAG.getMemset(getRoot(), sdl, Op1, Op2, Op3, Align, isVol,
|
bool isTC = I.isTailCall() && isInTailCallPosition(&I, DAG.getTarget());
|
||||||
MachinePointerInfo(I.getArgOperand(0))));
|
SDValue MS = DAG.getMemset(getRoot(), sdl, Op1, Op2, Op3, Align, isVol,
|
||||||
|
isTC, MachinePointerInfo(I.getArgOperand(0)));
|
||||||
|
updateDAGForMaybeTailCall(MS);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
case Intrinsic::memmove: {
|
case Intrinsic::memmove: {
|
||||||
@ -4631,9 +4636,11 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||||||
if (!Align)
|
if (!Align)
|
||||||
Align = 1; // @llvm.memmove defines 0 and 1 to both mean no alignment.
|
Align = 1; // @llvm.memmove defines 0 and 1 to both mean no alignment.
|
||||||
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
|
||||||
DAG.setRoot(DAG.getMemmove(getRoot(), sdl, Op1, Op2, Op3, Align, isVol,
|
bool isTC = I.isTailCall() && isInTailCallPosition(&I, DAG.getTarget());
|
||||||
MachinePointerInfo(I.getArgOperand(0)),
|
SDValue MM = DAG.getMemmove(getRoot(), sdl, Op1, Op2, Op3, Align, isVol,
|
||||||
MachinePointerInfo(I.getArgOperand(1))));
|
isTC, MachinePointerInfo(I.getArgOperand(0)),
|
||||||
|
MachinePointerInfo(I.getArgOperand(1)));
|
||||||
|
updateDAGForMaybeTailCall(MM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
case Intrinsic::dbg_declare: {
|
case Intrinsic::dbg_declare: {
|
||||||
@ -7794,3 +7801,17 @@ MachineBasicBlock *SelectionDAGBuilder::NextBlock(MachineBasicBlock *MBB) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
return I;
|
return I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// During lowering new call nodes can be created (such as memset, etc.).
|
||||||
|
/// Those will become new roots of the current DAG, but complications arise
|
||||||
|
/// when they are tail calls. In such cases, the call lowering will update
|
||||||
|
/// the root, but the builder still needs to know that a tail call has been
|
||||||
|
/// lowered in order to avoid generating an additional return.
|
||||||
|
void SelectionDAGBuilder::updateDAGForMaybeTailCall(SDValue MaybeTC) {
|
||||||
|
// If the node is null, we do have a tail call.
|
||||||
|
if (MaybeTC.getNode() != nullptr)
|
||||||
|
DAG.setRoot(MaybeTC);
|
||||||
|
else
|
||||||
|
HasTailCall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -829,6 +829,10 @@ private:
|
|||||||
|
|
||||||
/// Return the next block after MBB, or nullptr if there is none.
|
/// Return the next block after MBB, or nullptr if there is none.
|
||||||
MachineBasicBlock *NextBlock(MachineBasicBlock *MBB);
|
MachineBasicBlock *NextBlock(MachineBasicBlock *MBB);
|
||||||
|
|
||||||
|
/// Update the DAG and DAG builder with the relevant information after
|
||||||
|
/// a new root node has been created which could be a tail call.
|
||||||
|
void updateDAGForMaybeTailCall(SDValue MaybeTC);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -2744,8 +2744,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
|
|||||||
DAG.getConstant(Outs[i].Flags.getByValSize(), MVT::i64);
|
DAG.getConstant(Outs[i].Flags.getByValSize(), MVT::i64);
|
||||||
SDValue Cpy = DAG.getMemcpy(
|
SDValue Cpy = DAG.getMemcpy(
|
||||||
Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getByValAlign(),
|
Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getByValAlign(),
|
||||||
/*isVol = */ false,
|
/*isVol = */ false, /*AlwaysInline = */ false,
|
||||||
/*AlwaysInline = */ false, DstInfo, MachinePointerInfo());
|
/*isTailCall = */ false,
|
||||||
|
DstInfo, MachinePointerInfo());
|
||||||
|
|
||||||
MemOpChains.push_back(Cpy);
|
MemOpChains.push_back(Cpy);
|
||||||
} else {
|
} else {
|
||||||
@ -3976,7 +3977,7 @@ SDValue AArch64TargetLowering::LowerVACOPY(SDValue Op,
|
|||||||
|
|
||||||
return DAG.getMemcpy(Op.getOperand(0), SDLoc(Op), Op.getOperand(1),
|
return DAG.getMemcpy(Op.getOperand(0), SDLoc(Op), Op.getOperand(1),
|
||||||
Op.getOperand(2), DAG.getConstant(VaListSize, MVT::i32),
|
Op.getOperand(2), DAG.getConstant(VaListSize, MVT::i32),
|
||||||
8, false, false, MachinePointerInfo(DestSV),
|
8, false, false, false, MachinePointerInfo(DestSV),
|
||||||
MachinePointerInfo(SrcSV));
|
MachinePointerInfo(SrcSV));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,6 +316,7 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
|
|||||||
SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
|
SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
|
||||||
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
||||||
/*isVolatile=*/false, /*AlwaysInline=*/false,
|
/*isVolatile=*/false, /*AlwaysInline=*/false,
|
||||||
|
/*isTailCall=*/false,
|
||||||
MachinePointerInfo(), MachinePointerInfo());
|
MachinePointerInfo(), MachinePointerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +645,7 @@ MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
|||||||
Flags.getByValAlign(),
|
Flags.getByValAlign(),
|
||||||
/*isVolatile*/false,
|
/*isVolatile*/false,
|
||||||
/*AlwaysInline=*/true,
|
/*AlwaysInline=*/true,
|
||||||
|
/*isTailCall=*/false,
|
||||||
MachinePointerInfo(),
|
MachinePointerInfo(),
|
||||||
MachinePointerInfo());
|
MachinePointerInfo());
|
||||||
} else {
|
} else {
|
||||||
|
@ -3682,6 +3682,7 @@ void MipsTargetLowering::passByValArg(
|
|||||||
DAG.getIntPtrConstant(VA.getLocMemOffset()));
|
DAG.getIntPtrConstant(VA.getLocMemOffset()));
|
||||||
Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy),
|
Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy),
|
||||||
Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false,
|
Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false,
|
||||||
|
/*isTailCall=*/false,
|
||||||
MachinePointerInfo(), MachinePointerInfo());
|
MachinePointerInfo(), MachinePointerInfo());
|
||||||
MemOpChains.push_back(Chain);
|
MemOpChains.push_back(Chain);
|
||||||
}
|
}
|
||||||
|
@ -2221,7 +2221,7 @@ SDValue PPCTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG,
|
|||||||
// 2*sizeof(char) + 2 Byte alignment + 2*sizeof(char*) = 12 Byte
|
// 2*sizeof(char) + 2 Byte alignment + 2*sizeof(char*) = 12 Byte
|
||||||
return DAG.getMemcpy(Op.getOperand(0), Op,
|
return DAG.getMemcpy(Op.getOperand(0), Op,
|
||||||
Op.getOperand(1), Op.getOperand(2),
|
Op.getOperand(1), Op.getOperand(2),
|
||||||
DAG.getConstant(12, MVT::i32), 8, false, true,
|
DAG.getConstant(12, MVT::i32), 8, false, true, false,
|
||||||
MachinePointerInfo(), MachinePointerInfo());
|
MachinePointerInfo(), MachinePointerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3808,7 +3808,7 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
|
|||||||
SDLoc dl) {
|
SDLoc dl) {
|
||||||
SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
|
SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
|
||||||
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
||||||
false, false, MachinePointerInfo(),
|
false, false, false, MachinePointerInfo(),
|
||||||
MachinePointerInfo());
|
MachinePointerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,7 +727,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
|
|||||||
|
|
||||||
Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align,
|
Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align,
|
||||||
false, // isVolatile,
|
false, // isVolatile,
|
||||||
(Size <= 32), // AlwaysInline if size <= 32
|
(Size <= 32), // AlwaysInline if size <= 32,
|
||||||
|
false, // isTailCall
|
||||||
MachinePointerInfo(), MachinePointerInfo());
|
MachinePointerInfo(), MachinePointerInfo());
|
||||||
ByValArgs.push_back(FIPtr);
|
ByValArgs.push_back(FIPtr);
|
||||||
}
|
}
|
||||||
|
@ -2222,6 +2222,7 @@ SDValue SystemZTargetLowering::lowerVACOPY(SDValue Op,
|
|||||||
|
|
||||||
return DAG.getMemcpy(Chain, DL, DstPtr, SrcPtr, DAG.getIntPtrConstant(32),
|
return DAG.getMemcpy(Chain, DL, DstPtr, SrcPtr, DAG.getIntPtrConstant(32),
|
||||||
/*Align*/8, /*isVolatile*/false, /*AlwaysInline*/false,
|
/*Align*/8, /*isVolatile*/false, /*AlwaysInline*/false,
|
||||||
|
/*isTailCall*/false,
|
||||||
MachinePointerInfo(DstSV), MachinePointerInfo(SrcSV));
|
MachinePointerInfo(DstSV), MachinePointerInfo(SrcSV));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2143,6 +2143,7 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
|
|||||||
|
|
||||||
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
|
||||||
/*isVolatile*/false, /*AlwaysInline=*/true,
|
/*isVolatile*/false, /*AlwaysInline=*/true,
|
||||||
|
/*isTailCall*/false,
|
||||||
MachinePointerInfo(), MachinePointerInfo());
|
MachinePointerInfo(), MachinePointerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14494,7 +14495,7 @@ static SDValue LowerVACOPY(SDValue Op, const X86Subtarget *Subtarget,
|
|||||||
|
|
||||||
return DAG.getMemcpy(Chain, DL, DstPtr, SrcPtr,
|
return DAG.getMemcpy(Chain, DL, DstPtr, SrcPtr,
|
||||||
DAG.getIntPtrConstant(24), 8, /*isVolatile*/false,
|
DAG.getIntPtrConstant(24), 8, /*isVolatile*/false,
|
||||||
false,
|
false, false,
|
||||||
MachinePointerInfo(DstSV), MachinePointerInfo(SrcSV));
|
MachinePointerInfo(DstSV), MachinePointerInfo(SrcSV));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,8 @@ X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl,
|
|||||||
DAG.getConstant(Offset, AddrVT)),
|
DAG.getConstant(Offset, AddrVT)),
|
||||||
Src,
|
Src,
|
||||||
DAG.getConstant(BytesLeft, SizeVT),
|
DAG.getConstant(BytesLeft, SizeVT),
|
||||||
Align, isVolatile, DstPtrInfo.getWithOffset(Offset));
|
Align, isVolatile, false,
|
||||||
|
DstPtrInfo.getWithOffset(Offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
|
// TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
|
||||||
@ -282,7 +283,7 @@ SDValue X86SelectionDAGInfo::EmitTargetCodeForMemcpy(
|
|||||||
DAG.getNode(ISD::ADD, dl, SrcVT, Src,
|
DAG.getNode(ISD::ADD, dl, SrcVT, Src,
|
||||||
DAG.getConstant(Offset, SrcVT)),
|
DAG.getConstant(Offset, SrcVT)),
|
||||||
DAG.getConstant(BytesLeft, SizeVT),
|
DAG.getConstant(BytesLeft, SizeVT),
|
||||||
Align, isVolatile, AlwaysInline,
|
Align, isVolatile, AlwaysInline, false,
|
||||||
DstPtrInfo.getWithOffset(Offset),
|
DstPtrInfo.getWithOffset(Offset),
|
||||||
SrcPtrInfo.getWithOffset(Offset)));
|
SrcPtrInfo.getWithOffset(Offset)));
|
||||||
}
|
}
|
||||||
|
@ -1423,7 +1423,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
|
|||||||
InVals.push_back(FIN);
|
InVals.push_back(FIN);
|
||||||
MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV,
|
MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV,
|
||||||
DAG.getConstant(Size, MVT::i32),
|
DAG.getConstant(Size, MVT::i32),
|
||||||
Align, false, false,
|
Align, false, false, false,
|
||||||
MachinePointerInfo(),
|
MachinePointerInfo(),
|
||||||
MachinePointerInfo()));
|
MachinePointerInfo()));
|
||||||
} else {
|
} else {
|
||||||
@ -1834,10 +1834,11 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
|
|||||||
LD->getAlignment() == Alignment &&
|
LD->getAlignment() == Alignment &&
|
||||||
!LD->isVolatile() && !LD->isIndexed() &&
|
!LD->isVolatile() && !LD->isIndexed() &&
|
||||||
Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
|
Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
|
||||||
|
bool isTail = isInTailCallPosition(DAG, ST, Chain);
|
||||||
return DAG.getMemmove(Chain, dl, ST->getBasePtr(),
|
return DAG.getMemmove(Chain, dl, ST->getBasePtr(),
|
||||||
LD->getBasePtr(),
|
LD->getBasePtr(),
|
||||||
DAG.getConstant(StoreBits/8, MVT::i32),
|
DAG.getConstant(StoreBits/8, MVT::i32),
|
||||||
Alignment, false, ST->getPointerInfo(),
|
Alignment, false, isTail, ST->getPointerInfo(),
|
||||||
LD->getPointerInfo());
|
LD->getPointerInfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
test/CodeGen/AArch64/tailcall-mem-intrinsics.ll
Normal file
31
test/CodeGen/AArch64/tailcall-mem-intrinsics.ll
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; RUN: llc -march=aarch64 < %s | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memcpy:
|
||||||
|
; CHECK: b memcpy
|
||||||
|
define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memmove:
|
||||||
|
; CHECK: b memmove
|
||||||
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset:
|
||||||
|
; CHECK: b memset
|
||||||
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
31
test/CodeGen/ARM/tail-call-mem-intrinsics.ll
Normal file
31
test/CodeGen/ARM/tail-call-mem-intrinsics.ll
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; RUN: llc -march=arm < %s | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memcpy:
|
||||||
|
; CHECK: b memcpy
|
||||||
|
define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memmove:
|
||||||
|
; CHECK: b memmove
|
||||||
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset:
|
||||||
|
; CHECK: b memset
|
||||||
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
31
test/CodeGen/Hexagon/tail-call-mem-intrinsics.ll
Normal file
31
test/CodeGen/Hexagon/tail-call-mem-intrinsics.ll
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; RUN: llc -march=hexagon < %s | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memcpy:
|
||||||
|
; CHECK: jump memcpy
|
||||||
|
define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memmove:
|
||||||
|
; CHECK: jump memmove
|
||||||
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset:
|
||||||
|
; CHECK: jump memset
|
||||||
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
31
test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll
Normal file
31
test/CodeGen/SystemZ/tail-call-mem-intrinsics.ll
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; RUN: llc -march=systemz < %s | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memcpy:
|
||||||
|
; CHECK: jg memcpy
|
||||||
|
define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memmove:
|
||||||
|
; CHECK: jg memmove
|
||||||
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset:
|
||||||
|
; CHECK: jg memset
|
||||||
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
31
test/CodeGen/X86/tailcall-mem-intrinsics.ll
Normal file
31
test/CodeGen/X86/tailcall-mem-intrinsics.ll
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; RUN: llc -march=x86 < %s | FileCheck %s
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memcpy
|
||||||
|
; CHECK: jmp memcpy
|
||||||
|
define void @tail_memcpy(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset
|
||||||
|
; CHECK; jmp memmove
|
||||||
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: tail_memset
|
||||||
|
; CHECK: jmp memset
|
||||||
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
|
||||||
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
|
||||||
|
|
||||||
|
attributes #0 = { nounwind }
|
Loading…
Reference in New Issue
Block a user