| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s -check-prefix=X64 |
| |
| declare i256 @llvm.get.fpenv.i256() |
| declare void @llvm.set.fpenv.i256(i256 %fpenv) |
| declare void @llvm.reset.fpenv() |
| |
| ; Cannot fold get_fpenv+load+store because loaded value is used in |
| ; more than one instruction. |
| define void @get_fpenv_02(ptr %ptr1, ptr %ptr2) #0 { |
| ; X64-LABEL: get_fpenv_02: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %r14 |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: subq $40, %rsp |
| ; X64-NEXT: movq %rsi, %rbx |
| ; X64-NEXT: movq %rdi, %r14 |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fegetenv@PLT |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rax |
| ; X64-NEXT: movq (%rsp), %rcx |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rdx |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rsi |
| ; X64-NEXT: movq %rsi, 16(%r14) |
| ; X64-NEXT: movq %rcx, (%r14) |
| ; X64-NEXT: movq %rax, 24(%r14) |
| ; X64-NEXT: movq %rdx, 8(%r14) |
| ; X64-NEXT: movq %rsi, 16(%rbx) |
| ; X64-NEXT: movq %rcx, (%rbx) |
| ; X64-NEXT: movq %rax, 24(%rbx) |
| ; X64-NEXT: movq %rdx, 8(%rbx) |
| ; X64-NEXT: addq $40, %rsp |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: popq %r14 |
| ; X64-NEXT: retq |
| %fpenv = call i256 @llvm.get.fpenv.i256() |
| store i256 %fpenv, ptr %ptr1 |
| store i256 %fpenv, ptr %ptr2 |
| ret void |
| } |
| |
| ; Cannot fold get_fpenv+load+store because load and store have different type. |
| define void @get_fpenv_03(ptr %ptr) #0 { |
| ; X64-LABEL: get_fpenv_03: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: subq $32, %rsp |
| ; X64-NEXT: movq %rdi, %rbx |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fegetenv@PLT |
| ; X64-NEXT: movl (%rsp), %eax |
| ; X64-NEXT: movl %eax, (%rbx) |
| ; X64-NEXT: addq $32, %rsp |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: retq |
| %fpenv = call i256 @llvm.get.fpenv.i256() |
| %part = trunc i256 %fpenv to i32 |
| store i32 %part, ptr %ptr |
| ret void |
| } |
| |
| ; Cannot fold get_fpenv+load+store because loaded value is not |
| ; immediately stored. |
| define void @get_fpenv_04(ptr %ptr) #0 { |
| ; X64-LABEL: get_fpenv_04: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: subq $32, %rsp |
| ; X64-NEXT: movq %rdi, %rbx |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fegetenv@PLT |
| ; X64-NEXT: movq (%rsp), %rax |
| ; X64-NEXT: andl $1, %eax |
| ; X64-NEXT: movq %rax, (%rbx) |
| ; X64-NEXT: movq $0, 24(%rbx) |
| ; X64-NEXT: movq $0, 8(%rbx) |
| ; X64-NEXT: movq $0, 16(%rbx) |
| ; X64-NEXT: addq $32, %rsp |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: retq |
| %fpenv = call i256 @llvm.get.fpenv.i256() |
| %masked = and i256 %fpenv, 1 |
| store i256 %masked, ptr %ptr |
| ret void |
| } |
| |
| ; Cannot fold get_fpenv+load+store because there is a memory operation |
| ; between load and store. |
| define void @get_fpenv_05(ptr %ptr1, ptr %ptr2) #0 { |
| ; X64-LABEL: get_fpenv_05: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %r14 |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: subq $40, %rsp |
| ; X64-NEXT: movq %rsi, %rbx |
| ; X64-NEXT: movq %rdi, %r14 |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fegetenv@PLT |
| ; X64-NEXT: movq (%rsp), %rax |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rcx |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rdx |
| ; X64-NEXT: movq {{[0-9]+}}(%rsp), %rsi |
| ; X64-NEXT: movl $0, (%r14) |
| ; X64-NEXT: movq %rsi, 24(%rbx) |
| ; X64-NEXT: movq %rdx, 16(%rbx) |
| ; X64-NEXT: movq %rcx, 8(%rbx) |
| ; X64-NEXT: movq %rax, (%rbx) |
| ; X64-NEXT: addq $40, %rsp |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: popq %r14 |
| ; X64-NEXT: retq |
| %fpenv = call i256 @llvm.get.fpenv.i256() |
| store i32 0, ptr %ptr1 |
| store i256 %fpenv, ptr %ptr2 |
| ret void |
| } |
| |
| ; Cannot fold load+save+set_fpenv because there is a memory operation |
| ; between load and store. |
| define void @set_fpenv_02(ptr %ptr1, ptr %ptr2) #0 { |
| ; X64-LABEL: set_fpenv_02: |
| ; X64: # %bb.0: |
| ; X64-NEXT: subq $40, %rsp |
| ; X64-NEXT: movq (%rdi), %rax |
| ; X64-NEXT: movq 8(%rdi), %rcx |
| ; X64-NEXT: movq 16(%rdi), %rdx |
| ; X64-NEXT: movq 24(%rdi), %rdi |
| ; X64-NEXT: movl $0, (%rsi) |
| ; X64-NEXT: movq %rdi, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq %rdx, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq %rcx, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq %rax, (%rsp) |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fesetenv@PLT |
| ; X64-NEXT: addq $40, %rsp |
| ; X64-NEXT: retq |
| %fpenv = load i256, ptr %ptr1 |
| store i32 0, ptr %ptr2 |
| call void @llvm.set.fpenv.i256(i256 %fpenv) |
| ret void |
| } |
| |
| ; Cannot fold load+save+set_fpenv because loaded value is used in |
| ; more then one store. |
| define void @set_fpenv_03(ptr %ptr1, ptr %ptr2) #0 { |
| ; X64-LABEL: set_fpenv_03: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %r15 |
| ; X64-NEXT: pushq %r14 |
| ; X64-NEXT: pushq %r13 |
| ; X64-NEXT: pushq %r12 |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: subq $32, %rsp |
| ; X64-NEXT: movq %rsi, %rbx |
| ; X64-NEXT: movq (%rdi), %r14 |
| ; X64-NEXT: movq 8(%rdi), %r15 |
| ; X64-NEXT: movq 16(%rdi), %r12 |
| ; X64-NEXT: movq 24(%rdi), %r13 |
| ; X64-NEXT: callq fesetenv@PLT |
| ; X64-NEXT: movq %r13, 24(%rbx) |
| ; X64-NEXT: movq %r12, 16(%rbx) |
| ; X64-NEXT: movq %r15, 8(%rbx) |
| ; X64-NEXT: movq %r14, (%rbx) |
| ; X64-NEXT: addq $32, %rsp |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: popq %r12 |
| ; X64-NEXT: popq %r13 |
| ; X64-NEXT: popq %r14 |
| ; X64-NEXT: popq %r15 |
| ; X64-NEXT: retq |
| %fpenv = load i256, ptr %ptr1 |
| call void @llvm.set.fpenv.i256(i256 %fpenv) |
| store i256 %fpenv, ptr %ptr2 |
| ret void |
| } |
| |
| ; Cannot fold load+save+set_fpenv because loaded value is not |
| ; immediately stored. |
| define void @set_fpenv_04(ptr %ptr) #0 { |
| ; X64-LABEL: set_fpenv_04: |
| ; X64: # %bb.0: |
| ; X64-NEXT: subq $40, %rsp |
| ; X64-NEXT: movq (%rdi), %rax |
| ; X64-NEXT: andl $1, %eax |
| ; X64-NEXT: movq %rax, (%rsp) |
| ; X64-NEXT: movq $0, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq $0, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq $0, {{[0-9]+}}(%rsp) |
| ; X64-NEXT: movq %rsp, %rdi |
| ; X64-NEXT: callq fesetenv@PLT |
| ; X64-NEXT: addq $40, %rsp |
| ; X64-NEXT: retq |
| %fpenv = load i256, ptr %ptr |
| %masked = and i256 %fpenv, 1 |
| call void @llvm.set.fpenv.i256(i256 %masked) |
| ret void |
| } |
| |
| |
| attributes #0 = { nounwind "use-soft-float"="true" } |