Files
clang-p2996/llvm/test/CodeGen/X86/x87-stack-pop.mir
Serge Pavlov 3057e850b8 [X86] Preserve FPSW when popping x87 stack
When compiler converts x87 operations to stack model, it may insert
instructions that pop top stack element. To do it the compiler inserts
instruction FSTP right after the instruction that calculates value on
the stack. It can break the code that uses FPSW set by the last
instruction. For example, an instruction FXAM is usually followed by
FNSTSW, but FSTP is inserted after FXAM. As FSTP leaves condition code
in FPSW undefined, the compiler produces incorrect code.

With this change FSTP in inserted after the FPSW consumer if the last
instruction sets FPSW.

Differential Revision: https://reviews.llvm.org/D113335
2021-11-12 12:00:09 +07:00

68 lines
3.2 KiB
YAML

# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=i686-- -run-pass x86-codegen -O2 -o - %s | FileCheck %s
---
name: func_fxam
tracksRegLiveness: true
fixedStack:
- { id: 0, type: default, offset: 0, size: 10, alignment: 16 }
body: |
bb.0.entry:
; CHECK-LABEL: name: func_fxam
; CHECK: nofpexcept LD_F80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw, implicit-def $st0 :: (load (s80) from %fixed-stack.0, align 16)
; CHECK-NEXT: XAM_F implicit-def $fpsw, implicit $st0
; CHECK-NEXT: FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
; CHECK-NEXT: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw
; CHECK-NEXT: renamable $ax = KILL $ax, implicit-def $eax
; CHECK-NEXT: RET 0, $eax
renamable $fp0 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %fixed-stack.0, align 16)
XAM_Fp80 killed renamable $fp0, implicit-def $fpsw
FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
renamable $ax = KILL $ax, implicit-def $eax
RET 0, $eax
...
---
name: func_ftst
tracksRegLiveness: true
fixedStack:
- { id: 0, type: default, offset: 0, size: 10, alignment: 16 }
body: |
bb.0.entry:
; CHECK-LABEL: name: func_ftst
; CHECK: nofpexcept LD_F80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw, implicit-def $st0 :: (load (s80) from %fixed-stack.0, align 16)
; CHECK-NEXT: TST_F implicit-def $fpsw, implicit $fpcw, implicit $st0
; CHECK-NEXT: FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
; CHECK-NEXT: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw
; CHECK-NEXT: renamable $ax = KILL $ax, implicit-def $eax
; CHECK-NEXT: RET 0, $eax
renamable $fp0 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %fixed-stack.0, align 16)
TST_Fp80 killed renamable $fp0, implicit-def $fpsw, implicit $fpcw
FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
renamable $ax = KILL $ax, implicit-def $eax
RET 0, $eax
...
---
name: func_deaddef
tracksRegLiveness: true
fixedStack:
- { id: 0, type: default, offset: 0, size: 10, alignment: 16 }
body: |
bb.0.entry:
; CHECK-LABEL: name: func_deaddef
; CHECK: nofpexcept LD_F80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw, implicit-def $st0 :: (load (s80) from %fixed-stack.0, align 16)
; CHECK-NEXT: TST_F implicit-def dead $fpsw, implicit $fpcw, implicit $st0
; CHECK-NEXT: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw
; CHECK-NEXT: FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
; CHECK-NEXT: renamable $ax = KILL $ax, implicit-def $eax
; CHECK-NEXT: RET 0, $eax
renamable $fp0 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %fixed-stack.0, align 16)
TST_Fp80 killed renamable $fp0, implicit-def dead $fpsw, implicit $fpcw
FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw
renamable $ax = KILL $ax, implicit-def $eax
RET 0, $eax
...