diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1465,6 +1465,7 @@ // Turn FP extload into load/fpextend for (MVT VT : MVT::fp_valuetypes()) { + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand); } @@ -1474,6 +1475,8 @@ setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); // Turn FP truncstore into trunc + store. + setTruncStoreAction(MVT::f32, MVT::f16, Expand); + setTruncStoreAction(MVT::f64, MVT::f16, Expand); setTruncStoreAction(MVT::f64, MVT::f32, Expand); setTruncStoreAction(MVT::f128, MVT::f32, Expand); setTruncStoreAction(MVT::f128, MVT::f64, Expand); @@ -1515,6 +1518,12 @@ setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom); setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom); + // Lower f16 conversion operations into library calls + setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); + setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); + setOperationAction(ISD::BITCAST, MVT::f32, Expand); setOperationAction(ISD::BITCAST, MVT::i32, Expand); diff --git a/llvm/test/CodeGen/SPARC/fp16-promote.ll b/llvm/test/CodeGen/SPARC/fp16-promote.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPARC/fp16-promote.ll @@ -0,0 +1,376 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-BE +; RUN: llc -march=sparcel < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-EL +; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT +; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9 +; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s -check-prefix=SPARC64 + +define void @test_load_store(half* %p, half* %q) nounwind { +; V8-LABEL: test_load_store: +; V8: ! %bb.0: +; V8-NEXT: lduh [%o0], %o0 +; V8-NEXT: retl +; V8-NEXT: sth %o0, [%o1] +; +; V8-UNOPT-LABEL: test_load_store: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: lduh [%o0], %o0 +; V8-UNOPT-NEXT: retl +; V8-UNOPT-NEXT: sth %o0, [%o1] +; +; V9-LABEL: test_load_store: +; V9: ! %bb.0: +; V9-NEXT: lduh [%o0], %o0 +; V9-NEXT: retl +; V9-NEXT: sth %o0, [%o1] +; +; SPARC64-LABEL: test_load_store: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: lduh [%o0], %o0 +; SPARC64-NEXT: retl +; SPARC64-NEXT: sth %o0, [%o1] + %a = load half, half* %p + store half %a, half* %q + ret void +} + +define float @test_fpextend_float(half* %p) nounwind { +; V8-LABEL: test_fpextend_float: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -96, %sp +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i0], %o0 +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fpextend_float: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -96, %sp +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fpextend_float: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -96, %sp +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i0], %o0 +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fpextend_float: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -176, %sp +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i0], %o0 +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = load half, half* %p + %r = fpext half %a to float + ret float %r +} + +define double @test_fpextend_double(half* %p) nounwind { +; V8-LABEL: test_fpextend_double: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -96, %sp +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i0], %o0 +; V8-NEXT: fstod %f0, %f0 +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fpextend_double: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -96, %sp +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: fstod %f0, %f0 +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fpextend_double: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -96, %sp +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i0], %o0 +; V9-NEXT: fstod %f0, %f0 +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fpextend_double: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -176, %sp +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i0], %o0 +; SPARC64-NEXT: fstod %f0, %f0 +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = load half, half* %p + %r = fpext half %a to double + ret double %r +} + +define void @test_fptrunc_float(float %f, half* %p) nounwind { +; V8-LABEL: test_fptrunc_float: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -96, %sp +; V8-NEXT: call __gnu_f2h_ieee +; V8-NEXT: mov %i0, %o0 +; V8-NEXT: sth %o0, [%i1] +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fptrunc_float: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -104, %sp +; V8-UNOPT-NEXT: st %i0, [%fp+-4] +; V8-UNOPT-NEXT: ld [%fp+-4], %f0 +; V8-UNOPT-NEXT: mov %i0, %o0 +; V8-UNOPT-NEXT: st %i1, [%fp+-8] ! 4-byte Folded Spill +; V8-UNOPT-NEXT: call __gnu_f2h_ieee +; V8-UNOPT-NEXT: st %f0, [%fp+-12] +; V8-UNOPT-NEXT: ld [%fp+-8], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: sth %o0, [%i0] +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fptrunc_float: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -96, %sp +; V9-NEXT: call __gnu_f2h_ieee +; V9-NEXT: mov %i0, %o0 +; V9-NEXT: sth %o0, [%i1] +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fptrunc_float: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -176, %sp +; SPARC64-NEXT: call __gnu_f2h_ieee +; SPARC64-NEXT: nop +; SPARC64-NEXT: sth %o0, [%i1] +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = fptrunc float %f to half + store half %a, half* %p + ret void +} + +define void @test_fptrunc_double(double %d, half* %p) nounwind { +; V8-LABEL: test_fptrunc_double: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -112, %sp +; V8-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 def $i0_i1 +; 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: std %f0, [%fp+-16] +; V8-NEXT: call __truncdfhf2 +; V8-NEXT: ldd [%fp+-16], %o0 +; V8-NEXT: sth %o0, [%i2] +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fptrunc_double: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -112, %sp +; V8-UNOPT-NEXT: ! implicit-def: $i4_i5 +; V8-UNOPT-NEXT: mov %i0, %i4 +; V8-UNOPT-NEXT: mov %i1, %i5 +; V8-UNOPT-NEXT: std %i4, [%fp+-8] +; V8-UNOPT-NEXT: ldd [%fp+-8], %f0 +; V8-UNOPT-NEXT: std %f0, [%fp+-16] +; V8-UNOPT-NEXT: ldd [%fp+-16], %i0 +; V8-UNOPT-NEXT: mov %i0, %i3 +; V8-UNOPT-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 +; V8-UNOPT-NEXT: mov %i3, %o0 +; V8-UNOPT-NEXT: mov %i1, %o1 +; V8-UNOPT-NEXT: call __truncdfhf2 +; V8-UNOPT-NEXT: st %i2, [%fp+-20] +; V8-UNOPT-NEXT: ld [%fp+-20], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: sth %o0, [%i0] +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fptrunc_double: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -112, %sp +; V9-NEXT: ! kill: def $i1 killed $i1 killed $i0_i1 def $i0_i1 +; V9-NEXT: ! kill: def $i0 killed $i0 killed $i0_i1 def $i0_i1 +; V9-NEXT: std %i0, [%fp+-8] +; V9-NEXT: ldd [%fp+-8], %f0 +; V9-NEXT: std %f0, [%fp+-16] +; V9-NEXT: call __truncdfhf2 +; V9-NEXT: ldd [%fp+-16], %o0 +; V9-NEXT: sth %o0, [%i2] +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fptrunc_double: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -176, %sp +; SPARC64-NEXT: call __truncdfhf2 +; SPARC64-NEXT: nop +; SPARC64-NEXT: sth %o0, [%i1] +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = fptrunc double %d to half + store half %a, half* %p + ret void +} + +define void @test_fadd(half* %p, half* %q) nounwind { +; V8-LABEL: test_fadd: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -104, %sp +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i0], %o0 +; V8-NEXT: st %f0, [%fp+-8] ! 4-byte Folded Spill +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i1], %o0 +; V8-NEXT: ld [%fp+-8], %f1 ! 4-byte Folded Reload +; V8-NEXT: fadds %f1, %f0, %f0 +; V8-NEXT: st %f0, [%fp+-4] +; V8-NEXT: call __gnu_f2h_ieee +; V8-NEXT: ld [%fp+-4], %o0 +; V8-NEXT: sth %o0, [%i0] +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fadd: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -112, %sp +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: st %i1, [%fp+-8] ! 4-byte Folded Spill +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: st %i0, [%fp+-12] +; V8-UNOPT-NEXT: ld [%fp+-8], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: st %f0, [%fp+-16] +; V8-UNOPT-NEXT: ld [%fp+-16], %f1 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: fadds %f1, %f0, %f0 +; V8-UNOPT-NEXT: st %f0, [%fp+-4] +; V8-UNOPT-NEXT: call __gnu_f2h_ieee +; V8-UNOPT-NEXT: ld [%fp+-4], %o0 +; V8-UNOPT-NEXT: ld [%fp+-12], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: sth %o0, [%i0] +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fadd: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -104, %sp +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i0], %o0 +; V9-NEXT: st %f0, [%fp+-8] ! 4-byte Folded Spill +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i1], %o0 +; V9-NEXT: ld [%fp+-8], %f1 ! 4-byte Folded Reload +; V9-NEXT: fadds %f1, %f0, %f0 +; V9-NEXT: st %f0, [%fp+-4] +; V9-NEXT: call __gnu_f2h_ieee +; V9-NEXT: ld [%fp+-4], %o0 +; V9-NEXT: sth %o0, [%i0] +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fadd: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -192, %sp +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i0], %o0 +; SPARC64-NEXT: st %f0, [%fp+2043] ! 4-byte Folded Spill +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i1], %o0 +; SPARC64-NEXT: ld [%fp+2043], %f1 ! 4-byte Folded Reload +; SPARC64-NEXT: call __gnu_f2h_ieee +; SPARC64-NEXT: fadds %f1, %f0, %f1 +; SPARC64-NEXT: sth %o0, [%i0] +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = load half, half* %p + %b = load half, half* %q + %r = fadd half %a, %b + store half %r, half* %p + ret void +} + +define void @test_fmul(half* %p, half* %q) nounwind { +; V8-LABEL: test_fmul: +; V8: ! %bb.0: +; V8-NEXT: save %sp, -104, %sp +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i0], %o0 +; V8-NEXT: st %f0, [%fp+-8] ! 4-byte Folded Spill +; V8-NEXT: call __gnu_h2f_ieee +; V8-NEXT: lduh [%i1], %o0 +; V8-NEXT: ld [%fp+-8], %f1 ! 4-byte Folded Reload +; V8-NEXT: fmuls %f1, %f0, %f0 +; V8-NEXT: st %f0, [%fp+-4] +; V8-NEXT: call __gnu_f2h_ieee +; V8-NEXT: ld [%fp+-4], %o0 +; V8-NEXT: sth %o0, [%i0] +; V8-NEXT: ret +; V8-NEXT: restore +; +; V8-UNOPT-LABEL: test_fmul: +; V8-UNOPT: ! %bb.0: +; V8-UNOPT-NEXT: save %sp, -112, %sp +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: st %i1, [%fp+-8] ! 4-byte Folded Spill +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: st %i0, [%fp+-12] +; V8-UNOPT-NEXT: ld [%fp+-8], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: lduh [%i0], %o0 +; V8-UNOPT-NEXT: call __gnu_h2f_ieee +; V8-UNOPT-NEXT: st %f0, [%fp+-16] +; V8-UNOPT-NEXT: ld [%fp+-16], %f1 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: fmuls %f1, %f0, %f0 +; V8-UNOPT-NEXT: st %f0, [%fp+-4] +; V8-UNOPT-NEXT: call __gnu_f2h_ieee +; V8-UNOPT-NEXT: ld [%fp+-4], %o0 +; V8-UNOPT-NEXT: ld [%fp+-12], %i0 ! 4-byte Folded Reload +; V8-UNOPT-NEXT: sth %o0, [%i0] +; V8-UNOPT-NEXT: ret +; V8-UNOPT-NEXT: restore +; +; V9-LABEL: test_fmul: +; V9: ! %bb.0: +; V9-NEXT: save %sp, -104, %sp +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i0], %o0 +; V9-NEXT: st %f0, [%fp+-8] ! 4-byte Folded Spill +; V9-NEXT: call __gnu_h2f_ieee +; V9-NEXT: lduh [%i1], %o0 +; V9-NEXT: ld [%fp+-8], %f1 ! 4-byte Folded Reload +; V9-NEXT: fmuls %f1, %f0, %f0 +; V9-NEXT: st %f0, [%fp+-4] +; V9-NEXT: call __gnu_f2h_ieee +; V9-NEXT: ld [%fp+-4], %o0 +; V9-NEXT: sth %o0, [%i0] +; V9-NEXT: ret +; V9-NEXT: restore +; +; SPARC64-LABEL: test_fmul: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -192, %sp +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i0], %o0 +; SPARC64-NEXT: st %f0, [%fp+2043] ! 4-byte Folded Spill +; SPARC64-NEXT: call __gnu_h2f_ieee +; SPARC64-NEXT: lduh [%i1], %o0 +; SPARC64-NEXT: ld [%fp+2043], %f1 ! 4-byte Folded Reload +; SPARC64-NEXT: call __gnu_f2h_ieee +; SPARC64-NEXT: fmuls %f1, %f0, %f1 +; SPARC64-NEXT: sth %o0, [%i0] +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %a = load half, half* %p + %b = load half, half* %q + %r = fmul half %a, %b + store half %r, half* %p + ret void +}