From: Hans Wennborg Date: Thu, 14 Jan 2016 17:52:28 +0000 (+0000) Subject: Merging r257730: X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=25d64abdb39a834541edbafdc686f371dad58a76 Merging r257730: ------------------------------------------------------------------------ r257730 | majnemer | 2016-01-13 17:20:03 -0800 (Wed, 13 Jan 2016) | 11 lines [X86] Don't alter HasOpaqueSPAdjustment after we've relied on it We rely on HasOpaqueSPAdjustment not changing after we've calculated things based on it. Things like whether or not we can use 'rep;movs' to copy bytes around, that sort of thing. If it changes, invariants in the backend will quietly break. This situation arose when we had a call to memcpy *and* a COPY of the FLAGS register where we would attempt to reference local variables using %esi, a register that was clobbered by the 'rep;movs'. This fixes PR26124. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_38@257779 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 48e8ca75052..e50779aacc2 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -251,6 +251,10 @@ class MachineFrameInfo { /// opaque mechanism like inline assembly or Win32 EH. bool HasOpaqueSPAdjustment; + /// True if the function contains operations which will lower down to + /// instructions which manipulate the stack pointer. + bool HasCopyImplyingStackAdjustment; + /// True if the function contains a call to the llvm.vastart intrinsic. bool HasVAStart; @@ -288,6 +292,7 @@ public: LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; HasOpaqueSPAdjustment = false; + HasCopyImplyingStackAdjustment = false; HasVAStart = false; HasMustTailInVarArgFunc = false; Save = nullptr; @@ -493,6 +498,15 @@ public: bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; } void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; } + /// Returns true if the function contains operations which will lower down to + /// instructions which manipulate the stack pointer. + bool hasCopyImplyingStackAdjustment() const { + return HasCopyImplyingStackAdjustment; + } + void setHasCopyImplyingStackAdjustment(bool B) { + HasCopyImplyingStackAdjustment = B; + } + /// Returns true if the function calls the llvm.va_start intrinsic. bool hasVAStart() const { return HasVAStart; } void setHasVAStart(bool B) { HasVAStart = B; } diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 863b7cd044f..304da4f8751 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -2270,7 +2270,7 @@ public: } /// Return true if the MachineFunction contains a COPY which would imply - /// HasOpaqueSPAdjustment. + /// HasCopyImplyingStackAdjustment. virtual bool hasCopyImplyingStackAdjustment(MachineFunction *MF) const { return false; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 9f8759df0ba..c075da4738a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -634,7 +634,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { } if (TLI->hasCopyImplyingStackAdjustment(MF)) - MFI->setHasOpaqueSPAdjustment(true); + MFI->setHasCopyImplyingStackAdjustment(true); // Freeze the set of reserved registers now that MachineFrameInfo has been // set up. All the information required by getReservedRegs() should be diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 8b5fd27b477..8632bb8254f 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -91,7 +91,8 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const { MFI->isFrameAddressTaken() || MFI->hasOpaqueSPAdjustment() || MF.getInfo()->getForceFramePointer() || MMI.callsUnwindInit() || MMI.hasEHFunclets() || MMI.callsEHReturn() || - MFI->hasStackMap() || MFI->hasPatchPoint()); + MFI->hasStackMap() || MFI->hasPatchPoint() || + MFI->hasCopyImplyingStackAdjustment()); } static unsigned getSUBriOpcode(unsigned IsLP64, int64_t Imm) { @@ -943,11 +944,11 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // push and pop from the stack. if (Is64Bit && !Fn->hasFnAttribute(Attribute::NoRedZone) && !TRI->needsStackRealignment(MF) && - !MFI->hasVarSizedObjects() && // No dynamic alloca. - !MFI->adjustsStack() && // No calls. - !IsWin64CC && // Win64 has no Red Zone - !MFI->hasOpaqueSPAdjustment() && // Don't push and pop. - !MF.shouldSplitStack()) { // Regular stack + !MFI->hasVarSizedObjects() && // No dynamic alloca. + !MFI->adjustsStack() && // No calls. + !IsWin64CC && // Win64 has no Red Zone + !MFI->hasCopyImplyingStackAdjustment() && // Don't push and pop. + !MF.shouldSplitStack()) { // Regular stack uint64_t MinSize = X86FI->getCalleeSavedFrameSize(); if (HasFP) MinSize += SlotSize; StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1ec93b5f2d2..b723059f091 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -17458,7 +17458,7 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, // We need a frame pointer because this will get lowered to a PUSH/POP // sequence. MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); - MFI->setHasOpaqueSPAdjustment(true); + MFI->setHasCopyImplyingStackAdjustment(true); // Don't do anything here, we will expand these intrinsics out later // during ExpandISelPseudos in EmitInstrWithCustomInserter. return SDValue(); diff --git a/test/CodeGen/X86/x86-repmov-copy-eflags.ll b/test/CodeGen/X86/x86-repmov-copy-eflags.ll new file mode 100644 index 00000000000..ad398885728 --- /dev/null +++ b/test/CodeGen/X86/x86-repmov-copy-eflags.ll @@ -0,0 +1,53 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc18.0.0" + +%struct.T = type { i64, [3 x i32] } + +; Function Attrs: nounwind optsize +define void @f(i8* %p, i8* %q, i32* inalloca nocapture %unused) #0 { +entry: + %g = alloca %struct.T, align 8 + %r = alloca i32, align 8 + store i32 0, i32* %r, align 4 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 24, i32 8, i1 false) + br label %while.body + +while.body: ; preds = %while.body, %entry + %load = load i32, i32* %r, align 4 + %dec = add nsw i32 %load, -1 + store i32 %dec, i32* %r, align 4 + call void @g(%struct.T* %g) + %tobool = icmp eq i32 %dec, 0 + br i1 %tobool, label %while.end, label %while.body + +while.end: ; preds = %while.body + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #1 + +declare void @g(%struct.T*) + +; CHECK-LABEL: _f: +; CHECK: pushl %ebp +; CHECK: movl %esp, %ebp +; CHECK: andl $-8, %esp +; CHECK-NOT: movl %esp, %esi +; CHECK: rep;movsl +; CHECK: leal 8(%esp), %esi + +; CHECK: decl (%esp) +; CHECK: seto %al +; CHECK: lahf +; CHECK: movl %eax, %edi +; CHECK: pushl %esi +; CHECK: calll _g +; CHECK: addl $4, %esp +; CHECK: movl %edi, %eax +; CHECK: addb $127, %al +; CHECK: sahf + +attributes #0 = { nounwind optsize } +attributes #1 = { argmemonly nounwind }