diff options
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.diff | 263 |
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. |