mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Fix bug in x86 memcpy / memset lowering. If there are trailing bytes not handled by rep instructions, a new memcpy / memset is introduced for them. However, since source / destination addresses are already adjusted, their offsets should be zero.
llvm-svn: 50239
This commit is contained in:
parent
247bdc8ec7
commit
484060ba4a
@ -4822,7 +4822,7 @@ X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG,
|
||||
DAG.getConstant(Offset, AddrVT)),
|
||||
Src,
|
||||
DAG.getConstant(BytesLeft, SizeVT),
|
||||
Align, DstSV, Offset);
|
||||
Align, DstSV, 0);
|
||||
}
|
||||
|
||||
// TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
|
||||
@ -4847,8 +4847,6 @@ X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG,
|
||||
if (!AlwaysInline && SizeVal > getSubtarget()->getMaxInlineSizeThreshold())
|
||||
return SDOperand();
|
||||
|
||||
SmallVector<SDOperand, 4> Results;
|
||||
|
||||
MVT::ValueType AVT;
|
||||
unsigned BytesLeft = 0;
|
||||
if (Align >= 8 && Subtarget->is64Bit())
|
||||
@ -4881,25 +4879,24 @@ X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG,
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(DAG.getValueType(AVT));
|
||||
Ops.push_back(InFlag);
|
||||
Results.push_back(DAG.getNode(X86ISD::REP_MOVS, Tys, &Ops[0], Ops.size()));
|
||||
SDOperand RepMovs = DAG.getNode(X86ISD::REP_MOVS, Tys, &Ops[0], Ops.size());
|
||||
|
||||
SmallVector<SDOperand, 4> Results;
|
||||
Results.push_back(RepMovs);
|
||||
if (BytesLeft) {
|
||||
// Handle the last 1 - 7 bytes.
|
||||
unsigned Offset = SizeVal - BytesLeft;
|
||||
MVT::ValueType DstVT = Dst.getValueType();
|
||||
MVT::ValueType SrcVT = Src.getValueType();
|
||||
MVT::ValueType SizeVT = Size.getValueType();
|
||||
|
||||
Results.push_back(DAG.getMemcpy(Chain,
|
||||
Results.push_back(DAG.getMemcpy(Chain,
|
||||
DAG.getNode(ISD::ADD, DstVT, Dst,
|
||||
DAG.getConstant(Offset,
|
||||
DstVT)),
|
||||
DAG.getConstant(Offset, DstVT)),
|
||||
DAG.getNode(ISD::ADD, SrcVT, Src,
|
||||
DAG.getConstant(Offset,
|
||||
SrcVT)),
|
||||
DAG.getConstant(Offset, SrcVT)),
|
||||
DAG.getConstant(BytesLeft, SizeVT),
|
||||
Align, AlwaysInline,
|
||||
DstSV, Offset, SrcSV, Offset));
|
||||
DstSV, 0, SrcSV, 0));
|
||||
}
|
||||
|
||||
return DAG.getNode(ISD::TokenFactor, MVT::Other, &Results[0], Results.size());
|
||||
|
12
test/CodeGen/X86/2008-04-24-MemCpyBug.ll
Normal file
12
test/CodeGen/X86/2008-04-24-MemCpyBug.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-as < %s | llc -march=x86 | not grep 120
|
||||
; Don't accidentally add the offset twice for trailing bytes.
|
||||
|
||||
%struct.S63 = type { [63 x i8] }
|
||||
@g1s63 = external global %struct.S63 ; <%struct.S63*> [#uses=1]
|
||||
|
||||
declare void @test63(%struct.S63* byval align 4 ) nounwind
|
||||
|
||||
define void @testit63_entry_2E_ce() nounwind {
|
||||
tail call void @test63( %struct.S63* byval align 4 @g1s63 ) nounwind
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user