From: Chris Lattner Date: Thu, 21 Feb 2008 19:43:13 +0000 (+0000) Subject: Treat clobber operands like early clobbers: if we have X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0fe71e9bb19ff1781813184e41a8aaaae4dd2908;p=oota-llvm.git Treat clobber operands like early clobbers: if we have any, we force sdisel to do all regalloc for an asm. This leads to gross but correct codegen. This fixes the rest of PR2078. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47454 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index def4f9a0182..e159c111ded 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3467,6 +3467,17 @@ void AsmOperandInfo::ComputeConstraintToUse(const TargetLowering &TLI) { } +/// GetRegistersForValue - Assign registers (virtual or physical) for the +/// specified operand. We prefer to assign virtual registers, to allow the +/// register allocator handle the assignment process. However, if the asm uses +/// features that we can't model on machineinstrs, we have SDISel do the +/// allocation. This produces generally horrible, but correct, code. +/// +/// OpInfo describes the operand. +/// HasEarlyClobber is true if there are any early clobber constraints (=&r) +/// or any explicitly clobbered registers. +/// Input and OutputRegs are the set of already allocated physical registers. +/// void SelectionDAGLowering:: GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber, std::set &OutputRegs, @@ -3723,6 +3734,11 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // Keep track of whether we see an earlyclobber. SawEarlyClobber |= OpInfo.isEarlyClobber; + // If we see a clobber of a register, it is an early clobber. + if (OpInfo.Type == InlineAsm::isClobber && + OpInfo.ConstraintType == TargetLowering::C_Register) + SawEarlyClobber = true; + // If this is a memory input, and if the operand is not indirect, do what we // need to to provide an address for the memory input. if (OpInfo.ConstraintType == TargetLowering::C_Memory && diff --git a/test/CodeGen/X86/2008-02-20-InlineAsmClobber.ll b/test/CodeGen/X86/2008-02-20-InlineAsmClobber.ll index 94f4e18250a..d49d5bf9f9b 100644 --- a/test/CodeGen/X86/2008-02-20-InlineAsmClobber.ll +++ b/test/CodeGen/X86/2008-02-20-InlineAsmClobber.ll @@ -1,4 +1,5 @@ -; RUN: llvm-as < %s | llc | grep {%ecx %ecx} +; RUN: llvm-as < %s | llc | grep {a: %ecx %ecx} +; RUN: llvm-as < %s | llc | grep {b: %ecx %edx %ecx} ; PR2078 ; The clobber list says that "ax" is clobbered. Make sure that eax isn't ; allocated to the input/output register. @@ -9,7 +10,15 @@ target triple = "i386-apple-darwin8" define void @test() nounwind { entry: %tmp = load i32* @pixels, align 4 ; [#uses=1] - %tmp1 = tail call i32 asm sideeffect "$0 $1", "=r,0,~{dirflag},~{fpsr},~{flags},~{ax}"( i32 %tmp ) nounwind ; [#uses=1] + %tmp1 = tail call i32 asm sideeffect "a: $0 $1", "=r,0,~{dirflag},~{fpsr},~{flags},~{ax}"( i32 %tmp ) nounwind ; [#uses=1] store i32 %tmp1, i32* @pixels, align 4 ret void } + +define void @test2(i16* %block, i8* %pixels, i32 %line_size) nounwind { +entry: + %tmp1 = getelementptr i16* %block, i32 64 ; [#uses=1] + %tmp3 = tail call i8* asm sideeffect "b: $0 $1 $2", "=r,r,0,~{dirflag},~{fpsr},~{flags},~{ax}"( i16* %tmp1, i8* %pixels ) nounwind ; [#uses=0] + ret void +} +