summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff')
-rw-r--r--contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff263
1 files changed, 263 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff b/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff
new file mode 100644
index 0000000..b4017c9
--- /dev/null
+++ b/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff
@@ -0,0 +1,263 @@
+Pull in r202930 from upstream llvm trunk (by Hans Wennborg):
+
+ Check for dynamic allocas and inline asm that clobbers sp before building
+ selection dag (PR19012)
+
+ In X86SelectionDagInfo::EmitTargetCodeForMemcpy we check with MachineFrameInfo
+ to make sure that ESI isn't used as a base pointer register before we choose to
+ emit rep movs (which clobbers esi).
+
+ The problem is that MachineFrameInfo wouldn't know about dynamic allocas or
+ inline asm that clobbers the stack pointer until SelectionDAGBuilder has
+ encountered them.
+
+ This patch fixes the problem by checking for such things when building the
+ FunctionLoweringInfo.
+
+ Differential Revision: http://llvm-reviews.chandlerc.com/D2954
+
+Introduced here: http://svn.freebsd.org/changeset/base/263312
+
+Index: lib/CodeGen/MachineFunction.cpp
+===================================================================
+--- lib/CodeGen/MachineFunction.cpp
++++ lib/CodeGen/MachineFunction.cpp
+@@ -525,13 +525,14 @@ int MachineFrameInfo::CreateSpillStackObject(uint6
+ /// variable sized object is created, whether or not the index returned is
+ /// actually used.
+ ///
+-int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment) {
++int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment,
++ const AllocaInst *Alloca) {
+ HasVarSizedObjects = true;
+ Alignment =
+ clampStackAlignment(!getFrameLowering()->isStackRealignable() ||
+ !RealignOption,
+ Alignment, getFrameLowering()->getStackAlignment());
+- Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0));
++ Objects.push_back(StackObject(0, Alignment, 0, false, false, true, Alloca));
+ ensureMaxAlignment(Alignment);
+ return (int)Objects.size()-NumFixedObjects-1;
+ }
+Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+===================================================================
+--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+@@ -419,7 +419,7 @@ bool SelectionDAGISel::runOnMachineFunction(Machin
+ SplitCriticalSideEffectEdges(const_cast<Function&>(Fn), this);
+
+ CurDAG->init(*MF, TTI, TLI);
+- FuncInfo->set(Fn, *MF);
++ FuncInfo->set(Fn, *MF, CurDAG);
+
+ if (UseMBPI && OptLevel != CodeGenOpt::None)
+ FuncInfo->BPI = &getAnalysis<BranchProbabilityInfo>();
+@@ -429,7 +429,6 @@ bool SelectionDAGISel::runOnMachineFunction(Machin
+ SDB->init(GFI, *AA, LibInfo);
+
+ MF->setHasInlineAsm(false);
+- MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(false);
+
+ SelectAllBasicBlocks(Fn);
+
+Index: lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+===================================================================
+--- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
++++ lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+@@ -33,6 +33,7 @@
+ #include "llvm/Support/ErrorHandling.h"
+ #include "llvm/Support/MathExtras.h"
+ #include "llvm/Target/TargetInstrInfo.h"
++#include "llvm/Target/TargetFrameLowering.h"
+ #include "llvm/Target/TargetLowering.h"
+ #include "llvm/Target/TargetOptions.h"
+ #include "llvm/Target/TargetRegisterInfo.h"
+@@ -55,7 +56,8 @@ static bool isUsedOutsideOfDefiningBlock(const Ins
+ return false;
+ }
+
+-void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) {
++void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
++ SelectionDAG *DAG) {
+ const TargetLowering *TLI = TM.getTargetLowering();
+
+ Fn = &fn;
+@@ -100,6 +102,43 @@ static bool isUsedOutsideOfDefiningBlock(const Ins
+ for (; BB != EB; ++BB)
+ for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
+ I != E; ++I) {
++ // Look for dynamic allocas.
++ if (const AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
++ if (!AI->isStaticAlloca()) {
++ unsigned Align = std::max(
++ (unsigned)TLI->getDataLayout()->getPrefTypeAlignment(
++ AI->getAllocatedType()),
++ AI->getAlignment());
++ unsigned StackAlign = TM.getFrameLowering()->getStackAlignment();
++ if (Align <= StackAlign)
++ Align = 0;
++ // Inform the Frame Information that we have variable-sized objects.
++ MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1, AI);
++ }
++ }
++
++ // Look for inline asm that clobbers the SP register.
++ if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
++ ImmutableCallSite CS(I);
++ if (const InlineAsm *IA = dyn_cast<InlineAsm>(CS.getCalledValue())) {
++ unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
++ std::vector<TargetLowering::AsmOperandInfo> Ops =
++ TLI->ParseConstraints(CS);
++ for (size_t I = 0, E = Ops.size(); I != E; ++I) {
++ TargetLowering::AsmOperandInfo &Op = Ops[I];
++ if (Op.Type == InlineAsm::isClobber) {
++ // Clobbers don't have SDValue operands, hence SDValue().
++ TLI->ComputeConstraintToUse(Op, SDValue(), DAG);
++ std::pair<unsigned, const TargetRegisterClass*> PhysReg =
++ TLI->getRegForInlineAsmConstraint(Op.ConstraintCode,
++ Op.ConstraintVT);
++ if (PhysReg.first == SP)
++ MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(true);
++ }
++ }
++ }
++ }
++
+ // Mark values used outside their block as exported, by allocating
+ // a virtual register for them.
+ if (isUsedOutsideOfDefiningBlock(I))
+Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+===================================================================
+--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
++++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+@@ -860,10 +860,10 @@ void RegsForValue::AddInlineAsmOperands(unsigned C
+ unsigned TheReg = Regs[Reg++];
+ Ops.push_back(DAG.getRegister(TheReg, RegisterVT));
+
+- // Notice if we clobbered the stack pointer. Yes, inline asm can do this.
+ if (TheReg == SP && Code == InlineAsm::Kind_Clobber) {
+- MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+- MFI->setHasInlineAsmWithSPAdjust(true);
++ // If we clobbered the stack pointer, MFI should know about it.
++ assert(DAG.getMachineFunction().getFrameInfo()->
++ hasInlineAsmWithSPAdjust());
+ }
+ }
+ }
+@@ -3378,9 +3378,7 @@ void SelectionDAGBuilder::visitAlloca(const Alloca
+ setValue(&I, DSA);
+ DAG.setRoot(DSA.getValue(1));
+
+- // Inform the Frame Information that we have just allocated a variable-sized
+- // object.
+- FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1);
++ assert(FuncInfo.MF->getFrameInfo()->hasVarSizedObjects());
+ }
+
+ void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
+Index: test/CodeGen/X86/stack-align-memcpy.ll
+===================================================================
+--- test/CodeGen/X86/stack-align-memcpy.ll
++++ test/CodeGen/X86/stack-align-memcpy.ll
+@@ -2,6 +2,9 @@
+
+ %struct.foo = type { [88 x i8] }
+
++declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind
++declare void @baz(i8*) nounwind
++
+ ; PR15249
+ ; We can't use rep;movsl here because it clobbers the base pointer in %esi.
+ define void @test1(%struct.foo* nocapture %x, i32 %y) nounwind {
+@@ -15,4 +18,26 @@ define void @test1(%struct.foo* nocapture %x, i32
+ ; CHECK-NOT: rep;movsl
+ }
+
+-declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind
++; PR19012
++; Also don't clobber %esi if the dynamic alloca comes after the memcpy.
++define void @test2(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind {
++ call void @bar(i8* %z, %struct.foo* align 4 byval %x)
++ %dynalloc = alloca i8, i32 %y, align 1
++ call void @baz(i8* %dynalloc)
++ ret void
++
++; CHECK-LABEL: test2:
++; CHECK: movl %esp, %esi
++; CHECK-NOT: rep;movsl
++}
++
++; Check that we do use rep movs if we make the alloca static.
++define void @test3(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind {
++ call void @bar(i8* %z, %struct.foo* align 4 byval %x)
++ %statalloc = alloca i8, i32 8, align 1
++ call void @baz(i8* %statalloc)
++ ret void
++
++; CHECK-LABEL: test3:
++; CHECK: rep;movsl
++}
+Index: test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll
+===================================================================
+--- test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll
++++ test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll
+@@ -0,0 +1,17 @@
++; RUN: llc < %s -force-align-stack -mtriple i386-apple-darwin -mcpu=i486 | FileCheck %s
++
++%struct.foo = type { [88 x i8] }
++
++declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind
++
++; PR19012
++; Don't clobber %esi if we have inline asm that clobbers %esp.
++define void @test1(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind {
++ call void @bar(i8* %z, %struct.foo* align 4 byval %x)
++ call void asm sideeffect inteldialect "xor esp, esp", "=*m,~{flags},~{esp},~{esp},~{dirflag},~{fpsr},~{flags}"(i8* %z)
++ ret void
++
++; CHECK-LABEL: test1:
++; CHECK: movl %esp, %esi
++; CHECK-NOT: rep;movsl
++}
+Index: include/llvm/CodeGen/FunctionLoweringInfo.h
+===================================================================
+--- include/llvm/CodeGen/FunctionLoweringInfo.h
++++ include/llvm/CodeGen/FunctionLoweringInfo.h
+@@ -41,6 +41,7 @@ class MachineBasicBlock;
+ class MachineFunction;
+ class MachineModuleInfo;
+ class MachineRegisterInfo;
++class SelectionDAG;
+ class TargetLowering;
+ class Value;
+
+@@ -125,7 +126,7 @@ class FunctionLoweringInfo {
+ /// set - Initialize this FunctionLoweringInfo with the given Function
+ /// and its associated MachineFunction.
+ ///
+- void set(const Function &Fn, MachineFunction &MF);
++ void set(const Function &Fn, MachineFunction &MF, SelectionDAG *DAG);
+
+ /// clear - Clear out all the function-specific state. This returns this
+ /// FunctionLoweringInfo to an empty state, ready to be used for a
+Index: include/llvm/CodeGen/MachineFrameInfo.h
+===================================================================
+--- include/llvm/CodeGen/MachineFrameInfo.h
++++ include/llvm/CodeGen/MachineFrameInfo.h
+@@ -244,6 +244,7 @@ class MachineFrameInfo {
+ LocalFrameSize = 0;
+ LocalFrameMaxAlign = 0;
+ UseLocalStackAllocationBlock = false;
++ HasInlineAsmWithSPAdjust = false;
+ }
+
+ /// hasStackObjects - Return true if there are any stack objects in this
+@@ -529,7 +530,7 @@ class MachineFrameInfo {
+ /// variable sized object is created, whether or not the index returned is
+ /// actually used.
+ ///
+- int CreateVariableSizedObject(unsigned Alignment);
++ int CreateVariableSizedObject(unsigned Alignment, const AllocaInst *Alloca);
+
+ /// getCalleeSavedInfo - Returns a reference to call saved info vector for the
+ /// current function.
OpenPOWER on IntegriCloud