diff --git a/llvm/lib/Target/X86/X86FloatingPoint.cpp b/llvm/lib/Target/X86/X86FloatingPoint.cpp --- a/llvm/lib/Target/X86/X86FloatingPoint.cpp +++ b/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -1191,8 +1191,12 @@ // If this is the last use of the source register, just make sure it's on // the top of the stack. moveToTop(Reg, I); - if (StackTop == 0) - report_fatal_error("Stack cannot be empty!"); + if (StackTop == 0) { + if (MI.getOperand(1).isUndef()) + ++StackTop; + else + report_fatal_error("Stack cannot be empty!"); + } --StackTop; pushReg(getFPReg(MI.getOperand(0))); } else { diff --git a/llvm/test/CodeGen/X86/fpstack-call.mir b/llvm/test/CodeGen/X86/fpstack-call.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/fpstack-call.mir @@ -0,0 +1,52 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=x86_64-- -run-pass x86-codegen -verify-machineinstrs -mcpu=x86-64 -o - %s | FileCheck %s + +--- | + @x = dso_local global i32 0, align 4 + define void @fpstack-empty() { ret void } + declare void @foo() +... +--- + +name: fpstack-empty +tracksRegLiveness: true +registers: [] +liveins: + - { reg: '$r14', virtual-reg: '' } +stack: + - { id: 0, name: '', type: default, offset: 0, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: default, offset: 0, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.0 (%ir-block.0): + liveins: $r14 + ; CHECK-LABEL: name: fpstack-empty + ; CHECK: liveins: $r14 + ; CHECK: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + ; CHECK: renamable $rdi = MOV64ri @x + ; CHECK: renamable $rdx = LEA64r %stack.0, 1, $noreg, 0, $noreg + ; CHECK: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def dead $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp + ; CHECK: dead $esi = MOV32r0 implicit-def dead $eflags, implicit-def $rsi + ; CHECK: CALL64pcrel32 @foo, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx + ; CHECK: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + ; CHECK: renamable $xmm0 = MOVSDrm_alt %stack.1, 1, $noreg, 0, $noreg :: (load 8 from %stack.1) + ; CHECK: ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def dead $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp + ; CHECK: CHS_F implicit-def $fpsw + ; CHECK: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + ; CHECK: RETQ + ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + renamable $rdi = MOV64ri @x + renamable $rdx = LEA64r %stack.0, 1, $noreg, 0, $noreg + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def dead $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp + dead $esi = MOV32r0 implicit-def dead $eflags, implicit-def $rsi + CALL64pcrel32 @foo, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit-def dead $fp0 + renamable $xmm0 = MOVSDrm_alt %stack.1, 1, $noreg, 0, $noreg :: (load 8 from %stack.1) + ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def dead $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp + renamable $fp2 = CHS_Fp80 killed undef renamable $fp0, implicit-def $fpsw + + RETQ +... +---