blob: 0d92fc0d97f441c223875e7000f97a9d6fae9314 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=sparc -verify-machineinstrs -disable-strictnode-mutation < %s \
; RUN: | FileCheck %s --check-prefix=V8
; RUN: llc -mtriple=sparcv9 -verify-machineinstrs -disable-strictnode-mutation < %s \
; RUN: | FileCheck %s --check-prefix=V9
;; Constrained FP operations must select to the hardware instructions and must
;; not be constant folded or deleted when their exceptions are observable.
define float @fadd_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fadd_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fadds %f1, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fadd_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fadds %f1, %f3, %f0
%r = call float @llvm.experimental.constrained.fadd.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @fadd_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fadd_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: faddd %f2, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fadd_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: faddd %f0, %f2, %f0
%r = call double @llvm.experimental.constrained.fadd.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define float @fsub_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fsub_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fsubs %f1, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fsub_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fsubs %f1, %f3, %f0
%r = call float @llvm.experimental.constrained.fsub.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @fsub_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fsub_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fsubd %f2, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fsub_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fsubd %f0, %f2, %f0
%r = call double @llvm.experimental.constrained.fsub.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define float @fmul_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fmul_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fmuls %f1, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fmul_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fmuls %f1, %f3, %f0
%r = call float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @fmul_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fmul_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fmuld %f2, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fmul_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fmuld %f0, %f2, %f0
%r = call double @llvm.experimental.constrained.fmul.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define float @fdiv_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fdiv_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fdivs %f1, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fdiv_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fdivs %f1, %f3, %f0
%r = call float @llvm.experimental.constrained.fdiv.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @fdiv_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fdiv_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fdivd %f2, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fdiv_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fdivd %f0, %f2, %f0
%r = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define float @fsqrt_f32(float %a) nounwind strictfp {
; V8-LABEL: fsqrt_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -96, %sp
; V8-NEXT: st %o0, [%sp+92]
; V8-NEXT: ld [%sp+92], %f0
; V8-NEXT: fsqrts %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 96, %sp
;
; V9-LABEL: fsqrt_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fsqrts %f1, %f0
%r = call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @fsqrt_f64(double %a) nounwind strictfp {
; V8-LABEL: fsqrt_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+96]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: fsqrtd %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fsqrt_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fsqrtd %f0, %f0
%r = call double @llvm.experimental.constrained.sqrt.f64(double %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
;; Without hardware FMA this must become a libcall.
define double @fma_f64(double %a, double %b, double %c) nounwind strictfp {
; V8-LABEL: fma_f64:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -144, %sp
; V8-NEXT: ! kill: def $i5 killed $i5 killed $i4_i5 def $i4_i5
; V8-NEXT: ! kill: def $i3 killed $i3 killed $i2_i3 def $i2_i3
; V8-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 def $i0_i1
; V8-NEXT: ! kill: def $i4 killed $i4 killed $i4_i5 def $i4_i5
; V8-NEXT: std %i4, [%fp+-24]
; V8-NEXT: ! kill: def $i2 killed $i2 killed $i2_i3 def $i2_i3
; V8-NEXT: std %i2, [%fp+-16]
; V8-NEXT: ! kill: def $i0 killed $i0 killed $i0_i1 def $i0_i1
; V8-NEXT: std %i0, [%fp+-8]
; V8-NEXT: ldd [%fp+-8], %f0
; V8-NEXT: ldd [%fp+-16], %f2
; V8-NEXT: ldd [%fp+-24], %f4
; V8-NEXT: std %f0, [%fp+-48]
; V8-NEXT: std %f2, [%fp+-40]
; V8-NEXT: std %f4, [%fp+-32]
; V8-NEXT: ldd [%fp+-48], %o0
; V8-NEXT: ldd [%fp+-40], %o2
; V8-NEXT: call fma
; V8-NEXT: ldd [%fp+-32], %o4
; V8-NEXT: ret
; V8-NEXT: restore
;
; V9-LABEL: fma_f64:
; V9: ! %bb.0:
; V9-NEXT: save %sp, -176, %sp
; V9-NEXT: call fma
; V9-NEXT: nop
; V9-NEXT: ret
; V9-NEXT: restore
%r = call double @llvm.experimental.constrained.fma.f64(double %a, double %b, double %c, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define double @fpext_f32_f64(float %a) nounwind strictfp {
; V8-LABEL: fpext_f32_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -96, %sp
; V8-NEXT: st %o0, [%sp+92]
; V8-NEXT: ld [%sp+92], %f0
; V8-NEXT: fstod %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 96, %sp
;
; V9-LABEL: fpext_f32_f64:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fstod %f1, %f0
%r = call double @llvm.experimental.constrained.fpext.f64.f32(float %a, metadata !"fpexcept.strict") strictfp
ret double %r
}
define float @fptrunc_f64_f32(double %a) nounwind strictfp {
; V8-LABEL: fptrunc_f64_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+96]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: fdtos %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fptrunc_f64_f32:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fdtos %f0, %f0
%r = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define i32 @fptosi_f32_i32(float %a) nounwind strictfp {
; V8-LABEL: fptosi_f32_i32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o0, [%sp+100]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: fstoi %f0, %f0
; V8-NEXT: st %f0, [%sp+96]
; V8-NEXT: ld [%sp+96], %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fptosi_f32_i32:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: fstoi %f1, %f0
; V9-NEXT: st %f0, [%sp+2187]
; V9-NEXT: ld [%sp+2187], %o0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %a, metadata !"fpexcept.strict") strictfp
ret i32 %r
}
define i32 @fptosi_f64_i32(double %a) nounwind strictfp {
; V8-LABEL: fptosi_f64_i32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+96]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: fdtoi %f0, %f0
; V8-NEXT: st %f0, [%sp+92]
; V8-NEXT: ld [%sp+92], %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fptosi_f64_i32:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: fdtoi %f0, %f0
; V9-NEXT: st %f0, [%sp+2187]
; V9-NEXT: ld [%sp+2187], %o0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %a, metadata !"fpexcept.strict") strictfp
ret i32 %r
}
define i64 @fptosi_f64_i64(double %a) nounwind strictfp {
; V8-LABEL: fptosi_f64_i64:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -104, %sp
; V8-NEXT: mov %i1, %o1
; V8-NEXT: call __fixdfdi
; V8-NEXT: mov %i0, %o0
; V8-NEXT: mov %o0, %i0
; V8-NEXT: ret
; V8-NEXT: restore %g0, %o1, %o1
;
; V9-LABEL: fptosi_f64_i64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: fdtox %f0, %f0
; V9-NEXT: std %f0, [%sp+2183]
; V9-NEXT: ldx [%sp+2183], %o0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call i64 @llvm.experimental.constrained.fptosi.i64.f64(double %a, metadata !"fpexcept.strict") strictfp
ret i64 %r
}
define i32 @fptoui_f64_i32(double %a) nounwind strictfp {
; V8-LABEL: fptoui_f64_i32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+96]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: sethi %hi(.LCPI16_0), %o0
; V8-NEXT: ldd [%o0+%lo(.LCPI16_0)], %f2
; V8-NEXT: fcmped %f0, %f2
; V8-NEXT: nop
; V8-NEXT: fbl .LBB16_2
; V8-NEXT: mov %g0, %o0
; V8-NEXT: ! %bb.1:
; V8-NEXT: mov %o0, %o1
; V8-NEXT: cmp %o1, 0
; V8-NEXT: bne .LBB16_3
; V8-NEXT: nop
; V8-NEXT: ba .LBB16_4
; V8-NEXT: nop
; V8-NEXT: .LBB16_2:
; V8-NEXT: mov 1, %o1
; V8-NEXT: cmp %o1, 0
; V8-NEXT: be .LBB16_4
; V8-NEXT: nop
; V8-NEXT: .LBB16_3:
; V8-NEXT: sethi %hi(.LCPI16_1), %o2
; V8-NEXT: ldd [%o2+%lo(.LCPI16_1)], %f2
; V8-NEXT: .LBB16_4:
; V8-NEXT: fsubd %f0, %f2, %f0
; V8-NEXT: fdtoi %f0, %f0
; V8-NEXT: cmp %o1, 0
; V8-NEXT: bne .LBB16_6
; V8-NEXT: st %f0, [%sp+92]
; V8-NEXT: ! %bb.5:
; V8-NEXT: sethi 2097152, %o0
; V8-NEXT: .LBB16_6:
; V8-NEXT: ld [%sp+92], %o1
; V8-NEXT: xor %o1, %o0, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fptoui_f64_i32:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: mov %g0, %o0
; V9-NEXT: sethi %h44(.LCPI16_0), %o1
; V9-NEXT: add %o1, %m44(.LCPI16_0), %o1
; V9-NEXT: sllx %o1, 12, %o1
; V9-NEXT: ldd [%o1+%l44(.LCPI16_0)], %f2
; V9-NEXT: sethi %h44(.LCPI16_1), %o1
; V9-NEXT: add %o1, %m44(.LCPI16_1), %o1
; V9-NEXT: sllx %o1, 12, %o1
; V9-NEXT: ldd [%o1+%l44(.LCPI16_1)], %f4
; V9-NEXT: fcmped %fcc0, %f0, %f2
; V9-NEXT: movl %fcc0, 1, %o0
; V9-NEXT: cmp %o0, 0
; V9-NEXT: fmovdne %icc, %f4, %f2
; V9-NEXT: fsubd %f0, %f2, %f0
; V9-NEXT: fdtoi %f0, %f0
; V9-NEXT: st %f0, [%sp+2187]
; V9-NEXT: ld [%sp+2187], %o1
; V9-NEXT: cmp %o0, 0
; V9-NEXT: sethi 2097152, %o0
; V9-NEXT: movne %icc, 0, %o0
; V9-NEXT: xor %o1, %o0, %o0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %a, metadata !"fpexcept.strict") strictfp
ret i32 %r
}
define i64 @fptoui_f64_i64(double %a) nounwind strictfp {
; V8-LABEL: fptoui_f64_i64:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -104, %sp
; V8-NEXT: mov %i1, %o1
; V8-NEXT: call __fixunsdfdi
; V8-NEXT: mov %i0, %o0
; V8-NEXT: mov %o0, %i0
; V8-NEXT: ret
; V8-NEXT: restore %g0, %o1, %o1
;
; V9-LABEL: fptoui_f64_i64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: mov %g0, %o0
; V9-NEXT: sethi %h44(.LCPI17_0), %o1
; V9-NEXT: add %o1, %m44(.LCPI17_0), %o1
; V9-NEXT: sllx %o1, 12, %o1
; V9-NEXT: ldd [%o1+%l44(.LCPI17_0)], %f2
; V9-NEXT: sethi %h44(.LCPI17_1), %o1
; V9-NEXT: add %o1, %m44(.LCPI17_1), %o1
; V9-NEXT: sllx %o1, 12, %o1
; V9-NEXT: ldd [%o1+%l44(.LCPI17_1)], %f4
; V9-NEXT: fcmped %fcc0, %f0, %f2
; V9-NEXT: movl %fcc0, 1, %o0
; V9-NEXT: cmp %o0, 0
; V9-NEXT: fmovdne %icc, %f4, %f2
; V9-NEXT: fsubd %f0, %f2, %f0
; V9-NEXT: fdtox %f0, %f0
; V9-NEXT: std %f0, [%sp+2183]
; V9-NEXT: sethi 0, %o1
; V9-NEXT: or %o1, 0, %o1
; V9-NEXT: sethi 2097152, %o2
; V9-NEXT: or %o2, 0, %o2
; V9-NEXT: sllx %o2, 32, %o2
; V9-NEXT: ldx [%sp+2183], %o3
; V9-NEXT: or %o2, %o1, %o1
; V9-NEXT: cmp %o0, 0
; V9-NEXT: movne %icc, 0, %o1
; V9-NEXT: xor %o3, %o1, %o0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call i64 @llvm.experimental.constrained.fptoui.i64.f64(double %a, metadata !"fpexcept.strict") strictfp
ret i64 %r
}
define float @sitofp_i32_f32(i32 %a) nounwind strictfp {
; V8-LABEL: sitofp_i32_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -96, %sp
; V8-NEXT: st %o0, [%sp+92]
; V8-NEXT: ld [%sp+92], %f0
; V8-NEXT: fitos %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 96, %sp
;
; V9-LABEL: sitofp_i32_f32:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: st %o0, [%sp+2187]
; V9-NEXT: ld [%sp+2187], %f0
; V9-NEXT: fitos %f0, %f0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret float %r
}
define double @sitofp_i32_f64(i32 %a) nounwind strictfp {
; V8-LABEL: sitofp_i32_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -96, %sp
; V8-NEXT: st %o0, [%sp+92]
; V8-NEXT: ld [%sp+92], %f0
; V8-NEXT: fitod %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 96, %sp
;
; V9-LABEL: sitofp_i32_f64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: st %o0, [%sp+2187]
; V9-NEXT: ld [%sp+2187], %f0
; V9-NEXT: fitod %f0, %f0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define double @sitofp_i64_f64(i64 %a) nounwind strictfp {
; V8-LABEL: sitofp_i64_f64:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -96, %sp
; V8-NEXT: mov %i1, %o1
; V8-NEXT: call __floatdidf
; V8-NEXT: mov %i0, %o0
; V8-NEXT: ret
; V8-NEXT: restore
;
; V9-LABEL: sitofp_i64_f64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: stx %o0, [%sp+2183]
; V9-NEXT: ldd [%sp+2183], %f0
; V9-NEXT: fxtod %f0, %f0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call double @llvm.experimental.constrained.sitofp.f64.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define double @uitofp_i32_f64(i32 %a) nounwind strictfp {
; V8-LABEL: uitofp_i32_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: add %sp, 96, %o1
; V8-NEXT: or %o1, 4, %o1
; V8-NEXT: st %o0, [%o1]
; V8-NEXT: sethi 1100800, %o0
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: sethi %hi(.LCPI21_0), %o0
; V8-NEXT: ldd [%o0+%lo(.LCPI21_0)], %f2
; V8-NEXT: fsubd %f0, %f2, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: uitofp_i32_f64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: add %sp, 2183, %o1
; V9-NEXT: or %o1, 4, %o1
; V9-NEXT: st %o0, [%o1]
; V9-NEXT: sethi 1100800, %o0
; V9-NEXT: st %o0, [%sp+2183]
; V9-NEXT: ldd [%sp+2183], %f0
; V9-NEXT: sethi %h44(.LCPI21_0), %o0
; V9-NEXT: add %o0, %m44(.LCPI21_0), %o0
; V9-NEXT: sllx %o0, 12, %o0
; V9-NEXT: ldd [%o0+%l44(.LCPI21_0)], %f2
; V9-NEXT: fsubd %f0, %f2, %f0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
define double @uitofp_i64_f64(i64 %a) nounwind strictfp {
; V8-LABEL: uitofp_i64_f64:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -96, %sp
; V8-NEXT: mov %i1, %o1
; V8-NEXT: call __floatundidf
; V8-NEXT: mov %i0, %o0
; V8-NEXT: ret
; V8-NEXT: restore
;
; V9-LABEL: uitofp_i64_f64:
; V9: ! %bb.0:
; V9-NEXT: add %sp, -144, %sp
; V9-NEXT: srlx %o0, 1, %o1
; V9-NEXT: and %o0, 1, %o2
; V9-NEXT: or %o2, %o1, %o1
; V9-NEXT: mov %o0, %o2
; V9-NEXT: movrlz %o0, %o1, %o2
; V9-NEXT: stx %o2, [%sp+2183]
; V9-NEXT: ldd [%sp+2183], %f0
; V9-NEXT: fxtod %f0, %f0
; V9-NEXT: faddd %f0, %f0, %f2
; V9-NEXT: fmovrdlz %o0, %f2, %f0
; V9-NEXT: retl
; V9-NEXT: add %sp, 144, %sp
%r = call double @llvm.experimental.constrained.uitofp.f64.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret double %r
}
;; Quiet compares use fcmp, signaling compares use fcmpe.
define i32 @fcmp_olt_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fcmp_olt_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fcmpd %f2, %f0
; V8-NEXT: nop
; V8-NEXT: fbl .LBB23_2
; V8-NEXT: nop
; V8-NEXT: ! %bb.1:
; V8-NEXT: mov %g0, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
; V8-NEXT: .LBB23_2:
; V8-NEXT: mov 1, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fcmp_olt_f64:
; V9: ! %bb.0:
; V9-NEXT: mov %g0, %o0
; V9-NEXT: fcmpd %fcc0, %f0, %f2
; V9-NEXT: movl %fcc0, 1, %o0
; V9-NEXT: retl
; V9-NEXT: srl %o0, 0, %o0
%c = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"olt", metadata !"fpexcept.strict") strictfp
%r = zext i1 %c to i32
ret i32 %r
}
define i32 @fcmps_olt_f64(double %a, double %b) nounwind strictfp {
; V8-LABEL: fcmps_olt_f64:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fcmped %f2, %f0
; V8-NEXT: nop
; V8-NEXT: fbl .LBB24_2
; V8-NEXT: nop
; V8-NEXT: ! %bb.1:
; V8-NEXT: mov %g0, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
; V8-NEXT: .LBB24_2:
; V8-NEXT: mov 1, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fcmps_olt_f64:
; V9: ! %bb.0:
; V9-NEXT: mov %g0, %o0
; V9-NEXT: fcmped %fcc0, %f0, %f2
; V9-NEXT: movl %fcc0, 1, %o0
; V9-NEXT: retl
; V9-NEXT: srl %o0, 0, %o0
%c = call i1 @llvm.experimental.constrained.fcmps.f64(double %a, double %b, metadata !"olt", metadata !"fpexcept.strict") strictfp
%r = zext i1 %c to i32
ret i32 %r
}
define i32 @fcmp_ueq_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fcmp_ueq_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fcmps %f1, %f0
; V8-NEXT: nop
; V8-NEXT: fbue .LBB25_2
; V8-NEXT: nop
; V8-NEXT: ! %bb.1:
; V8-NEXT: mov %g0, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
; V8-NEXT: .LBB25_2:
; V8-NEXT: mov 1, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fcmp_ueq_f32:
; V9: ! %bb.0:
; V9-NEXT: mov %g0, %o0
; V9-NEXT: fcmps %fcc0, %f1, %f3
; V9-NEXT: movue %fcc0, 1, %o0
; V9-NEXT: retl
; V9-NEXT: srl %o0, 0, %o0
%c = call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp
%r = zext i1 %c to i32
ret i32 %r
}
define i32 @fcmps_oeq_f32(float %a, float %b) nounwind strictfp {
; V8-LABEL: fcmps_oeq_f32:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -104, %sp
; V8-NEXT: st %o1, [%sp+100]
; V8-NEXT: st %o0, [%sp+96]
; V8-NEXT: ld [%sp+100], %f0
; V8-NEXT: ld [%sp+96], %f1
; V8-NEXT: fcmpes %f1, %f0
; V8-NEXT: nop
; V8-NEXT: fbe .LBB26_2
; V8-NEXT: nop
; V8-NEXT: ! %bb.1:
; V8-NEXT: mov %g0, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
; V8-NEXT: .LBB26_2:
; V8-NEXT: mov 1, %o0
; V8-NEXT: retl
; V8-NEXT: add %sp, 104, %sp
;
; V9-LABEL: fcmps_oeq_f32:
; V9: ! %bb.0:
; V9-NEXT: mov %g0, %o0
; V9-NEXT: fcmpes %fcc0, %f1, %f3
; V9-NEXT: move %fcc0, 1, %o0
; V9-NEXT: retl
; V9-NEXT: srl %o0, 0, %o0
%c = call i1 @llvm.experimental.constrained.fcmps.f32(float %a, float %b, metadata !"oeq", metadata !"fpexcept.strict") strictfp
%r = zext i1 %c to i32
ret i32 %r
}
define void @fcmps_branch(double %a, double %b) nounwind strictfp {
; V8-LABEL: fcmps_branch:
; V8: ! %bb.0: ! %entry
; V8-NEXT: save %sp, -112, %sp
; V8-NEXT: ! kill: def $i3 killed $i3 killed $i2_i3 def $i2_i3
; V8-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 def $i0_i1
; V8-NEXT: ! kill: def $i2 killed $i2 killed $i2_i3 def $i2_i3
; V8-NEXT: std %i2, [%fp+-16]
; V8-NEXT: ! kill: def $i0 killed $i0 killed $i0_i1 def $i0_i1
; V8-NEXT: std %i0, [%fp+-8]
; V8-NEXT: ldd [%fp+-16], %f0
; V8-NEXT: ldd [%fp+-8], %f2
; V8-NEXT: fcmped %f2, %f0
; V8-NEXT: nop
; V8-NEXT: fbule .LBB27_2
; V8-NEXT: nop
; V8-NEXT: ! %bb.1: ! %entry
; V8-NEXT: mov %g0, %i0
; V8-NEXT: cmp %i0, 0
; V8-NEXT: be .LBB27_3
; V8-NEXT: nop
; V8-NEXT: ba .LBB27_4
; V8-NEXT: nop
; V8-NEXT: .LBB27_2:
; V8-NEXT: mov 1, %i0
; V8-NEXT: cmp %i0, 0
; V8-NEXT: bne .LBB27_4
; V8-NEXT: nop
; V8-NEXT: .LBB27_3: ! %if.then
; V8-NEXT: call foo
; V8-NEXT: nop
; V8-NEXT: .LBB27_4: ! %if.end
; V8-NEXT: ret
; V8-NEXT: restore
;
; V9-LABEL: fcmps_branch:
; V9: ! %bb.0: ! %entry
; V9-NEXT: save %sp, -176, %sp
; V9-NEXT: mov %g0, %i0
; V9-NEXT: fcmped %fcc0, %f0, %f2
; V9-NEXT: movule %fcc0, 1, %i0
; V9-NEXT: cmp %i0, 0
; V9-NEXT: bne %icc, .LBB27_2
; V9-NEXT: nop
; V9-NEXT: ! %bb.1: ! %if.then
; V9-NEXT: call foo
; V9-NEXT: nop
; V9-NEXT: .LBB27_2: ! %if.end
; V9-NEXT: ret
; V9-NEXT: restore
entry:
%c = call i1 @llvm.experimental.constrained.fcmps.f64(double %a, double %b, metadata !"ogt", metadata !"fpexcept.strict") strictfp
br i1 %c, label %if.then, label %if.end
if.then:
call void @foo() strictfp
br label %if.end
if.end:
ret void
}
;; The result of the division is unused, but it may raise an exception, so it
;; must be kept.
define void @fdiv_unused(double %a, double %b) nounwind strictfp {
; V8-LABEL: fdiv_unused:
; V8: ! %bb.0:
; V8-NEXT: add %sp, -112, %sp
; V8-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
; V8-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
; V8-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
; V8-NEXT: std %o2, [%sp+96]
; V8-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; V8-NEXT: std %o0, [%sp+104]
; V8-NEXT: ldd [%sp+96], %f0
; V8-NEXT: ldd [%sp+104], %f2
; V8-NEXT: fdivd %f2, %f0, %f0
; V8-NEXT: retl
; V8-NEXT: add %sp, 112, %sp
;
; V9-LABEL: fdiv_unused:
; V9: ! %bb.0:
; V9-NEXT: retl
; V9-NEXT: fdivd %f0, %f2, %f0
%r = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
ret void
}
;; The division must stay between the two calls that may change the rounding
;; mode.
define double @fdiv_between_calls(double %a, double %b) nounwind strictfp {
; V8-LABEL: fdiv_between_calls:
; V8: ! %bb.0:
; V8-NEXT: save %sp, -128, %sp
; V8-NEXT: ! kill: def $i3 killed $i3 killed $i2_i3 def $i2_i3
; V8-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 def $i0_i1
; V8-NEXT: ! kill: def $i2 killed $i2 killed $i2_i3 def $i2_i3
; V8-NEXT: std %i2, [%fp+-16]
; V8-NEXT: ! kill: def $i0 killed $i0 killed $i0_i1 def $i0_i1
; V8-NEXT: std %i0, [%fp+-8]
; V8-NEXT: ldd [%fp+-16], %f0
; V8-NEXT: std %f0, [%fp+-24] ! 8-byte Folded Spill
; V8-NEXT: ldd [%fp+-8], %f0
; V8-NEXT: call foo
; V8-NEXT: std %f0, [%fp+-32]
; V8-NEXT: ldd [%fp+-24], %f0 ! 8-byte Folded Reload
; V8-NEXT: ldd [%fp+-32], %f2 ! 8-byte Folded Reload
; V8-NEXT: fdivd %f2, %f0, %f0
; V8-NEXT: call foo
; V8-NEXT: std %f0, [%fp+-24]
; V8-NEXT: ldd [%fp+-24], %f0 ! 8-byte Folded Reload
; V8-NEXT: ret
; V8-NEXT: restore
;
; V9-LABEL: fdiv_between_calls:
; V9: ! %bb.0:
; V9-NEXT: save %sp, -192, %sp
; V9-NEXT: std %f2, [%fp+2039] ! 8-byte Folded Spill
; V9-NEXT: call foo
; V9-NEXT: std %f0, [%fp+2031]
; V9-NEXT: ldd [%fp+2039], %f0 ! 8-byte Folded Reload
; V9-NEXT: ldd [%fp+2031], %f2 ! 8-byte Folded Reload
; V9-NEXT: fdivd %f2, %f0, %f0
; V9-NEXT: call foo
; V9-NEXT: std %f0, [%fp+2039]
; V9-NEXT: ldd [%fp+2039], %f0 ! 8-byte Folded Reload
; V9-NEXT: ret
; V9-NEXT: restore
call void @foo() strictfp
%r = call double @llvm.experimental.constrained.fdiv.f64(double %a, double %b, metadata !"round.dynamic", metadata !"fpexcept.strict") strictfp
call void @foo() strictfp
ret double %r
}
declare void @foo()