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
68 lines
3.2 KiB
YAML
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
|
|
|
|
...
|