From 82a46ebe0a0e0042463bfb3fec427e94c798db18 Mon Sep 17 00:00:00 2001 From: Elena Demikhovsky Date: Mon, 14 Oct 2013 07:26:51 +0000 Subject: [PATCH] Fixed a bug in dynamic allocation memory on stack. The alignment of allocated space was wrong, see Bugzila 17345. Done by Zvi Rackover . llvm-svn: 192573 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 6 +-- llvm/lib/Target/X86/X86ISelLowering.cpp | 17 ++++-- .../CodeGen/Thumb2/2010-04-15-DynAllocBug.ll | 4 +- llvm/test/CodeGen/X86/dyn_alloca_aligned.ll | 9 ++++ .../CodeGen/X86/win64_alloca_dynalloca.ll | 52 ++++++++++++++++++- 5 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 llvm/test/CodeGen/X86/dyn_alloca_aligned.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index ee373f8040b5..d805d2c4c761 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1581,10 +1581,10 @@ void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node, Chain = SP.getValue(1); unsigned Align = cast(Tmp3)->getZExtValue(); unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); - if (Align > StackAlign) - SP = DAG.getNode(ISD::AND, dl, VT, SP, - DAG.getConstant(-(uint64_t)Align, VT)); Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value + if (Align > StackAlign) + Tmp1 = DAG.getNode(ISD::AND, dl, VT, Tmp1, + DAG.getConstant(-(uint64_t)Align, VT)); Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true), diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index bd5ad4e264fe..47ce3ac8cf91 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -10755,7 +10755,8 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, // Get the inputs. SDValue Chain = Op.getOperand(0); SDValue Size = Op.getOperand(1); - // FIXME: Ensure alignment here + unsigned Align = cast(Op.getOperand(2))->getZExtValue(); + EVT VT = Op.getNode()->getValueType(0); bool Is64Bit = Subtarget->is64Bit(); EVT SPTy = Is64Bit ? MVT::i64 : MVT::i32; @@ -10793,14 +10794,20 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag); - Flag = Chain.getValue(1); const X86RegisterInfo *RegInfo = static_cast(getTargetMachine().getRegisterInfo()); - Chain = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(), - SPTy).getValue(1); + unsigned SPReg = RegInfo->getStackRegister(); + SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, SPTy); + Chain = SP.getValue(1); - SDValue Ops1[2] = { Chain.getValue(0), Chain }; + if (Align) { + SP = DAG.getNode(ISD::AND, dl, VT, SP.getValue(0), + DAG.getConstant(-(uint64_t)Align, VT)); + Chain = DAG.getCopyToReg(Chain, dl, SPReg, SP); + } + + SDValue Ops1[2] = { SP, Chain }; return DAG.getMergeValues(Ops1, 2, dl); } } diff --git a/llvm/test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll b/llvm/test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll index 486c064cfa7a..1b8bdb1c19bb 100644 --- a/llvm/test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll +++ b/llvm/test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll @@ -8,10 +8,10 @@ define void @t() nounwind ssp { entry: ; CHECK-LABEL: t: %size = mul i32 8, 2 -; CHECK: subs r0, #16 +; CHECK: sub.w r0, sp, #16 ; CHECK: mov sp, r0 %vla_a = alloca i8, i32 %size, align 8 -; CHECK: subs r0, #16 +; CHECK: sub.w r0, sp, #16 ; CHECK: mov sp, r0 %vla_b = alloca i8, i32 %size, align 8 unreachable diff --git a/llvm/test/CodeGen/X86/dyn_alloca_aligned.ll b/llvm/test/CodeGen/X86/dyn_alloca_aligned.ll new file mode 100644 index 000000000000..993f4d2af75d --- /dev/null +++ b/llvm/test/CodeGen/X86/dyn_alloca_aligned.ll @@ -0,0 +1,9 @@ +; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s +define i32 @A(i32 %Size) { +; CHECK: subq %rcx, %rax +; CHECK: andq $-128, %rax +; CHECK: movq %rax, %rsp + %A = alloca i8, i32 %Size, align 128 + %A_addr = ptrtoint i8* %A to i32 + ret i32 %A_addr +} diff --git a/llvm/test/CodeGen/X86/win64_alloca_dynalloca.ll b/llvm/test/CodeGen/X86/win64_alloca_dynalloca.ll index 275ebf94893c..9752edb912cd 100644 --- a/llvm/test/CodeGen/X86/win64_alloca_dynalloca.ll +++ b/llvm/test/CodeGen/X86/win64_alloca_dynalloca.ll @@ -4,7 +4,10 @@ ; PR8777 ; PR8778 -define i64 @foo(i64 %n, i64 %x) nounwind { +define i64 @unaligned(i64 %n, i64 %x) nounwind { +; M64-LABEL: unaligned: +; W64-LABEL: unaligned: +; EFI-LABEL: unaligned: entry: %buf0 = alloca i8, i64 4096, align 1 @@ -71,4 +74,51 @@ entry: } +define i64 @aligned(i64 %n, i64 %x) nounwind { +; M64-LABEL: aligned: +; W64-LABEL: aligned: +; EFI-LABEL: aligned: +entry: + + %buf1 = alloca i8, i64 %n, align 128 + +; M64: leaq 15(%{{.*}}), %rax +; M64: andq $-16, %rax +; M64: callq ___chkstk +; M64: movq %rsp, [[R2:%r.*]] +; M64: andq $-128, [[R2]] +; M64: movq [[R2]], %rsp + +; W64: leaq 15(%{{.*}}), %rax +; W64: andq $-16, %rax +; W64: callq __chkstk +; W64: subq %rax, %rsp +; W64: movq %rsp, [[R2:%r.*]] +; W64: andq $-128, [[R2]] +; W64: movq [[R2]], %rsp + +; EFI: leaq 15(%{{.*}}), [[R1:%r.*]] +; EFI: andq $-16, [[R1]] +; EFI: movq %rsp, [[R64:%r.*]] +; EFI: subq [[R1]], [[R64]] +; EFI: andq $-128, [[R64]] +; EFI: movq [[R64]], %rsp + + %r = call i64 @bar(i64 %n, i64 %x, i64 %n, i8* undef, i8* %buf1) nounwind + +; M64: subq $48, %rsp +; M64: movq [[R2]], 32(%rsp) +; M64: callq bar + +; W64: subq $48, %rsp +; W64: movq [[R2]], 32(%rsp) +; W64: callq bar + +; EFI: subq $48, %rsp +; EFI: movq [[R64]], 32(%rsp) +; EFI: callq _bar + + ret i64 %r +} + declare i64 @bar(i64, i64, i64, i8* nocapture, i8* nocapture) nounwind