| ; 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() |