/// is below the threshold. It returns the types of the sequence of
/// memory ops to perform memset / memcpy by reference.
static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps,
- SDValue Dst, SDValue Src,
unsigned Limit, uint64_t Size,
unsigned DstAlign, unsigned SrcAlign,
+ bool SafeToUseFP,
SelectionDAG &DAG,
const TargetLowering &TLI) {
assert((SrcAlign == 0 || SrcAlign >= DstAlign) &&
// the inferred alignment of the source. 'DstAlign', on the other hand, is the
// specified alignment of the memory operation. If it is zero, that means
// it's possible to change the alignment of the destination.
- EVT VT = TLI.getOptimalMemOpType(Size, DstAlign, SrcAlign, DAG);
+ EVT VT = TLI.getOptimalMemOpType(Size, DstAlign, SrcAlign, SafeToUseFP, DAG);
if (VT == MVT::Other) {
VT = TLI.getPointerTy();
std::string Str;
bool CopyFromStr = isMemSrcFromString(Src, Str);
bool isZeroStr = CopyFromStr && Str.empty();
- if (!FindOptimalMemOpLowering(MemOps, Dst, Src, Limit, Size,
+ if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
(DstAlignCanChange ? 0 : Align),
- (isZeroStr ? 0 : SrcAlign), DAG, TLI))
+ (isZeroStr ? 0 : SrcAlign), true, DAG, TLI))
return SDValue();
if (DstAlignCanChange) {
if (Align > SrcAlign)
SrcAlign = Align;
- if (!FindOptimalMemOpLowering(MemOps, Dst, Src, Limit, Size,
+ if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
(DstAlignCanChange ? 0 : Align),
- SrcAlign, DAG, TLI))
+ SrcAlign, true, DAG, TLI))
return SDValue();
if (DstAlignCanChange) {
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
if (FI && !MFI->isFixedObjectIndex(FI->getIndex()))
DstAlignCanChange = true;
- if (!FindOptimalMemOpLowering(MemOps, Dst, Src, TLI.getMaxStoresPerMemset(),
+ bool IsZero = isa<ConstantSDNode>(Src) &&
+ cast<ConstantSDNode>(Src)->isNullValue();
+ if (!FindOptimalMemOpLowering(MemOps, TLI.getMaxStoresPerMemset(),
Size, (DstAlignCanChange ? 0 : Align), 0,
- DAG, TLI))
+ IsZero, DAG, TLI))
return SDValue();
if (DstAlignCanChange) {
unsigned Align = GV->getAlignment();
if (!Align) {
if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
- const TargetData *TD = TLI.getTargetData();
- Align = TD->getPreferredAlignment(GVar);
+ if (GV->getType()->getElementType()->isSized()) {
+ const TargetData *TD = TLI.getTargetData();
+ Align = TD->getPreferredAlignment(GVar);
+ }
}
}
return MinAlign(Align, GVOffset);
EVT
X86TargetLowering::getOptimalMemOpType(uint64_t Size,
unsigned DstAlign, unsigned SrcAlign,
+ bool SafeToUseFP,
SelectionDAG &DAG) const {
// FIXME: This turns off use of xmm stores for memset/memcpy on targets like
// linux. This is because the stack realignment code can't handle certain
Subtarget->getStackAlignment() >= 16) {
if (Subtarget->hasSSE2())
return MVT::v4i32;
- if (Subtarget->hasSSE1())
+ if (SafeToUseFP && Subtarget->hasSSE1())
return MVT::v4f32;
- } else if (Size >= 8 &&
+ } else if (SafeToUseFP &&
+ Size >= 8 &&
Subtarget->getStackAlignment() >= 8 &&
Subtarget->hasSSE2())
return MVT::f64;