diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -1237,6 +1237,18 @@ Register Reg = MO.getReg(); if (!Reg) continue; + // Do not free later early-clobbered registers when MI is MSVCInlineAsm + if (MI.isMSInlineAsm()) { + unsigned J = 0; + for (J = I + 1; J != MI.getNumOperands(); ++J) { + MachineOperand &LaterMO = MI.getOperand(J); + if (LaterMO.isReg() && LaterMO.getReg() == Reg && + MI.getOperand(J).isEarlyClobber()) + break; + } + if (J != MI.getNumOperands()) + continue; + } assert(Reg.isPhysical()); if (MRI->isReserved(Reg)) continue; diff --git a/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.ll b/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.ll @@ -0,0 +1,15 @@ +; RUN: llc < %s -O0 -mtriple=i386-unknown-linux-gnu -mcpu=generic -regalloc=fast -optimize-regalloc=0 -no-x86-call-frame-opt | FileCheck %s + +define dso_local i32 @foo() { +entry: +; CHECK: movl $1, %eax +; CHECK-NOT: movl %eax, (%eax) + %retval = alloca i32, align 4 + %c = alloca { [4 x i32] }, align 4 + store i32 0, i32* %retval, align 4 + %m32 = bitcast { [4 x i32] }* %c to [4 x i32]* + %0 = call i32 asm sideeffect inteldialect "mov eax,$$1\0A\09mov $0,eax", "=*m,={eax},~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %m32) #1, !srcloc !3 + store i32 %0, i32* %retval, align 4 + ret i32 0 +} +!3 = !{i32 285} \ No newline at end of file diff --git a/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.mir b/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/corner-msInline-fastregalloc.mir @@ -0,0 +1,64 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s + +# Make sure this case doesn't try to assign $eax to %5 + +--- | + ; ModuleID = '' + source_filename = "test.c" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + + define dso_local i32 @foo() { + entry: + %retval = alloca i32, align 4 + %c = alloca { [4 x i32] }, align 4 + store i32 0, i32* %retval, align 4 + %m32 = bitcast { [4 x i32] }* %c to [4 x i32]* + %0 = call i32 asm sideeffect inteldialect "mov eax,$$1\0A\09mov $0,eax", "=*m,={eax},~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %m32), !srcloc !0 + store i32 %0, i32* %retval, align 4 + ret i32 0 + } + + !0 = !{i32 285} + +... +--- +name: foo +alignment: 16 +tracksRegLiveness: true +registers: + - { id: 0, class: gr32 } + - { id: 1, class: gr32 } + - { id: 2, class: gr64 } + - { id: 3, class: gr32 } + - { id: 4, class: gr64 } + - { id: 5, class: gr64 } +frameInfo: + maxAlignment: 8 +stack: + - { id: 0, name: retval, size: 4, alignment: 4 } + - { id: 1, name: c, size: 16, alignment: 8 } +machineFunctionInfo: {} +body: | + bb.0.entry: + ; CHECK-LABEL: name: foo + ; CHECK: MOV32mi %stack.0.retval, 1, $noreg, 0, $noreg, 0 :: (store 4 into %ir.retval) + ; CHECK: renamable $rcx = LEA64r %stack.1.c, 1, $noreg, 0, $noreg + ; CHECK: INLINEASM &"mov eax,$$1\0A\09mov $0,eax", 21 /* sideeffect maystore */, 196654 /* mem:m */, killed renamable $rcx, 1, $noreg, 0, $noreg, 10 /* regdef */, implicit-def $eax, 12 /* clobber */, implicit-def early-clobber $eax, 12 /* clobber */, implicit-def dead early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def dead early-clobber $eflags, !0 + ; CHECK: renamable $ecx = COPY killed $eax + ; CHECK: renamable $eax = MOV32r0 implicit-def dead $eflags + ; CHECK: MOV32mr %stack.0.retval, 1, $noreg, 0, $noreg, killed renamable $ecx :: (store 4 into %ir.retval) + ; CHECK: RETQ implicit killed $eax + MOV32mi %stack.0.retval, 1, $noreg, 0, $noreg, 0 :: (store 4 into %ir.retval) + %4:gr64 = LEA64r %stack.1.c, 1, $noreg, 0, $noreg + %5:gr64 = COPY %4 + INLINEASM &"mov eax,$$1\0A\09mov $0,eax", 21 /* sideeffect maystore */, 196654 /* mem:m */, %5, 1, $noreg, 0, $noreg, 10 /* regdef */, implicit-def $eax, 12 /* clobber */, implicit-def early-clobber $eax, 12 /* clobber */, implicit-def early-clobber $df, 12 /* clobber */, implicit-def early-clobber $fpsw, 12 /* clobber */, implicit-def early-clobber $eflags, !0 + %3:gr32 = COPY $eax + %1:gr32 = COPY %3 + %0:gr32 = MOV32r0 implicit-def $eflags + MOV32mr %stack.0.retval, 1, $noreg, 0, $noreg, killed %1 :: (store 4 into %ir.retval) + $eax = COPY %0 + RETQ implicit $eax + +... +