From 2749c72f30a6d424a09a0f8dc87e42e103d8315b Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 25 Apr 2008 00:26:43 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50239 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 19 ++++++++----------- test/CodeGen/X86/2008-04-24-MemCpyBug.ll | 12 ++++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 test/CodeGen/X86/2008-04-24-MemCpyBug.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9ba1f53f88d..a0fd3d90c5e 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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 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 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()); diff --git a/test/CodeGen/X86/2008-04-24-MemCpyBug.ll b/test/CodeGen/X86/2008-04-24-MemCpyBug.ll new file mode 100644 index 00000000000..09fdc707b85 --- /dev/null +++ b/test/CodeGen/X86/2008-04-24-MemCpyBug.ll @@ -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 +}