|  | ; 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" } |