415 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-linux-gnu | FileCheck %s --check-prefix=X86-NOF16C3; RUN: llc < %s -mtriple=i686-linux-gnu -mattr=f16c | FileCheck %s --check-prefix=X86-F16C4; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefix=X64-NOF16C5; RUN: llc < %s -mtriple=x86_64-linux-gnu -mattr=f16c | FileCheck %s --check-prefix=X64-F16C6 7@a = global half 0xH0000, align 28@b = global half 0xH0000, align 29@c = global half 0xH0000, align 210 11define float @half_to_float() strictfp {12; X86-NOF16C-LABEL: half_to_float:13; X86-NOF16C: # %bb.0:14; X86-NOF16C-NEXT: subl $12, %esp15; X86-NOF16C-NEXT: .cfi_def_cfa_offset 1616; X86-NOF16C-NEXT: movzwl a, %eax17; X86-NOF16C-NEXT: movl %eax, (%esp)18; X86-NOF16C-NEXT: calll __extendhfsf219; X86-NOF16C-NEXT: addl $12, %esp20; X86-NOF16C-NEXT: .cfi_def_cfa_offset 421; X86-NOF16C-NEXT: retl22;23; X86-F16C-LABEL: half_to_float:24; X86-F16C: # %bb.0:25; X86-F16C-NEXT: pushl %eax26; X86-F16C-NEXT: .cfi_def_cfa_offset 827; X86-F16C-NEXT: movzwl a, %eax28; X86-F16C-NEXT: vmovd %eax, %xmm029; X86-F16C-NEXT: vcvtph2ps %xmm0, %xmm030; X86-F16C-NEXT: vmovss %xmm0, (%esp)31; X86-F16C-NEXT: flds (%esp)32; X86-F16C-NEXT: wait33; X86-F16C-NEXT: popl %eax34; X86-F16C-NEXT: .cfi_def_cfa_offset 435; X86-F16C-NEXT: retl36;37; X64-NOF16C-LABEL: half_to_float:38; X64-NOF16C: # %bb.0:39; X64-NOF16C-NEXT: pushq %rax40; X64-NOF16C-NEXT: .cfi_def_cfa_offset 1641; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rax42; X64-NOF16C-NEXT: pinsrw $0, (%rax), %xmm043; X64-NOF16C-NEXT: callq __extendhfsf2@PLT44; X64-NOF16C-NEXT: popq %rax45; X64-NOF16C-NEXT: .cfi_def_cfa_offset 846; X64-NOF16C-NEXT: retq47;48; X64-F16C-LABEL: half_to_float:49; X64-F16C: # %bb.0:50; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax51; X64-F16C-NEXT: movzwl (%rax), %eax52; X64-F16C-NEXT: vmovd %eax, %xmm053; X64-F16C-NEXT: vcvtph2ps %xmm0, %xmm054; X64-F16C-NEXT: retq55 %1 = load half, ptr @a, align 256 %2 = tail call float @llvm.experimental.constrained.fpext.f32.f16(half %1, metadata !"fpexcept.strict") #057 ret float %258}59 60define double @half_to_double() strictfp {61; X86-NOF16C-LABEL: half_to_double:62; X86-NOF16C: # %bb.0:63; X86-NOF16C-NEXT: subl $12, %esp64; X86-NOF16C-NEXT: .cfi_def_cfa_offset 1665; X86-NOF16C-NEXT: movzwl a, %eax66; X86-NOF16C-NEXT: movl %eax, (%esp)67; X86-NOF16C-NEXT: calll __extendhfsf268; X86-NOF16C-NEXT: addl $12, %esp69; X86-NOF16C-NEXT: .cfi_def_cfa_offset 470; X86-NOF16C-NEXT: retl71;72; X86-F16C-LABEL: half_to_double:73; X86-F16C: # %bb.0:74; X86-F16C-NEXT: subl $12, %esp75; X86-F16C-NEXT: .cfi_def_cfa_offset 1676; X86-F16C-NEXT: movzwl a, %eax77; X86-F16C-NEXT: vmovd %eax, %xmm078; X86-F16C-NEXT: vcvtph2ps %xmm0, %xmm079; X86-F16C-NEXT: vcvtss2sd %xmm0, %xmm0, %xmm080; X86-F16C-NEXT: vmovsd %xmm0, (%esp)81; X86-F16C-NEXT: fldl (%esp)82; X86-F16C-NEXT: wait83; X86-F16C-NEXT: addl $12, %esp84; X86-F16C-NEXT: .cfi_def_cfa_offset 485; X86-F16C-NEXT: retl86;87; X64-NOF16C-LABEL: half_to_double:88; X64-NOF16C: # %bb.0:89; X64-NOF16C-NEXT: pushq %rax90; X64-NOF16C-NEXT: .cfi_def_cfa_offset 1691; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rax92; X64-NOF16C-NEXT: pinsrw $0, (%rax), %xmm093; X64-NOF16C-NEXT: callq __extendhfsf2@PLT94; X64-NOF16C-NEXT: cvtss2sd %xmm0, %xmm095; X64-NOF16C-NEXT: popq %rax96; X64-NOF16C-NEXT: .cfi_def_cfa_offset 897; X64-NOF16C-NEXT: retq98;99; X64-F16C-LABEL: half_to_double:100; X64-F16C: # %bb.0:101; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax102; X64-F16C-NEXT: movzwl (%rax), %eax103; X64-F16C-NEXT: vmovd %eax, %xmm0104; X64-F16C-NEXT: vcvtph2ps %xmm0, %xmm0105; X64-F16C-NEXT: vcvtss2sd %xmm0, %xmm0, %xmm0106; X64-F16C-NEXT: retq107 %1 = load half, ptr @a, align 2108 %2 = tail call double @llvm.experimental.constrained.fpext.f64.f16(half %1, metadata !"fpexcept.strict") #0109 ret double %2110}111 112define x86_fp80 @half_to_fp80() strictfp {113; X86-NOF16C-LABEL: half_to_fp80:114; X86-NOF16C: # %bb.0:115; X86-NOF16C-NEXT: subl $12, %esp116; X86-NOF16C-NEXT: .cfi_def_cfa_offset 16117; X86-NOF16C-NEXT: movzwl a, %eax118; X86-NOF16C-NEXT: movl %eax, (%esp)119; X86-NOF16C-NEXT: calll __extendhfsf2120; X86-NOF16C-NEXT: addl $12, %esp121; X86-NOF16C-NEXT: .cfi_def_cfa_offset 4122; X86-NOF16C-NEXT: retl123;124; X86-F16C-LABEL: half_to_fp80:125; X86-F16C: # %bb.0:126; X86-F16C-NEXT: subl $12, %esp127; X86-F16C-NEXT: .cfi_def_cfa_offset 16128; X86-F16C-NEXT: vpinsrw $0, a, %xmm0, %xmm0129; X86-F16C-NEXT: vpextrw $0, %xmm0, (%esp)130; X86-F16C-NEXT: calll __extendhfxf2131; X86-F16C-NEXT: addl $12, %esp132; X86-F16C-NEXT: .cfi_def_cfa_offset 4133; X86-F16C-NEXT: retl134;135; X64-NOF16C-LABEL: half_to_fp80:136; X64-NOF16C: # %bb.0:137; X64-NOF16C-NEXT: pushq %rax138; X64-NOF16C-NEXT: .cfi_def_cfa_offset 16139; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rax140; X64-NOF16C-NEXT: pinsrw $0, (%rax), %xmm0141; X64-NOF16C-NEXT: callq __extendhfxf2@PLT142; X64-NOF16C-NEXT: popq %rax143; X64-NOF16C-NEXT: .cfi_def_cfa_offset 8144; X64-NOF16C-NEXT: retq145;146; X64-F16C-LABEL: half_to_fp80:147; X64-F16C: # %bb.0:148; X64-F16C-NEXT: pushq %rax149; X64-F16C-NEXT: .cfi_def_cfa_offset 16150; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax151; X64-F16C-NEXT: vpinsrw $0, (%rax), %xmm0, %xmm0152; X64-F16C-NEXT: callq __extendhfxf2@PLT153; X64-F16C-NEXT: popq %rax154; X64-F16C-NEXT: .cfi_def_cfa_offset 8155; X64-F16C-NEXT: retq156 %1 = load half, ptr @a, align 2157 %2 = tail call x86_fp80 @llvm.experimental.constrained.fpext.f80.f16(half %1, metadata !"fpexcept.strict") #0158 ret x86_fp80 %2159}160 161define void @float_to_half(float %0) strictfp {162; X86-NOF16C-LABEL: float_to_half:163; X86-NOF16C: # %bb.0:164; X86-NOF16C-NEXT: subl $12, %esp165; X86-NOF16C-NEXT: .cfi_def_cfa_offset 16166; X86-NOF16C-NEXT: flds {{[0-9]+}}(%esp)167; X86-NOF16C-NEXT: fstps (%esp)168; X86-NOF16C-NEXT: wait169; X86-NOF16C-NEXT: calll __truncsfhf2170; X86-NOF16C-NEXT: movw %ax, a171; X86-NOF16C-NEXT: addl $12, %esp172; X86-NOF16C-NEXT: .cfi_def_cfa_offset 4173; X86-NOF16C-NEXT: retl174;175; X86-F16C-LABEL: float_to_half:176; X86-F16C: # %bb.0:177; X86-F16C-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero178; X86-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0179; X86-F16C-NEXT: vpextrw $0, %xmm0, a180; X86-F16C-NEXT: retl181;182; X64-NOF16C-LABEL: float_to_half:183; X64-NOF16C: # %bb.0:184; X64-NOF16C-NEXT: pushq %rax185; X64-NOF16C-NEXT: .cfi_def_cfa_offset 16186; X64-NOF16C-NEXT: callq __truncsfhf2@PLT187; X64-NOF16C-NEXT: pextrw $0, %xmm0, %eax188; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rcx189; X64-NOF16C-NEXT: movw %ax, (%rcx)190; X64-NOF16C-NEXT: popq %rax191; X64-NOF16C-NEXT: .cfi_def_cfa_offset 8192; X64-NOF16C-NEXT: retq193;194; X64-F16C-LABEL: float_to_half:195; X64-F16C: # %bb.0:196; X64-F16C-NEXT: vxorps %xmm1, %xmm1, %xmm1197; X64-F16C-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]198; X64-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0199; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax200; X64-F16C-NEXT: vpextrw $0, %xmm0, (%rax)201; X64-F16C-NEXT: retq202 %2 = tail call half @llvm.experimental.constrained.fptrunc.f16.f32(float %0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0203 store half %2, ptr @a, align 2204 ret void205}206 207define void @double_to_half(double %0) strictfp {208; X86-NOF16C-LABEL: double_to_half:209; X86-NOF16C: # %bb.0:210; X86-NOF16C-NEXT: subl $12, %esp211; X86-NOF16C-NEXT: .cfi_def_cfa_offset 16212; X86-NOF16C-NEXT: fldl {{[0-9]+}}(%esp)213; X86-NOF16C-NEXT: fstpl (%esp)214; X86-NOF16C-NEXT: wait215; X86-NOF16C-NEXT: calll __truncdfhf2216; X86-NOF16C-NEXT: movw %ax, a217; X86-NOF16C-NEXT: addl $12, %esp218; X86-NOF16C-NEXT: .cfi_def_cfa_offset 4219; X86-NOF16C-NEXT: retl220;221; X86-F16C-LABEL: double_to_half:222; X86-F16C: # %bb.0:223; X86-F16C-NEXT: subl $12, %esp224; X86-F16C-NEXT: .cfi_def_cfa_offset 16225; X86-F16C-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero226; X86-F16C-NEXT: vmovq %xmm0, (%esp)227; X86-F16C-NEXT: calll __truncdfhf2228; X86-F16C-NEXT: vpextrw $0, %xmm0, a229; X86-F16C-NEXT: addl $12, %esp230; X86-F16C-NEXT: .cfi_def_cfa_offset 4231; X86-F16C-NEXT: retl232;233; X64-NOF16C-LABEL: double_to_half:234; X64-NOF16C: # %bb.0:235; X64-NOF16C-NEXT: pushq %rax236; X64-NOF16C-NEXT: .cfi_def_cfa_offset 16237; X64-NOF16C-NEXT: callq __truncdfhf2@PLT238; X64-NOF16C-NEXT: pextrw $0, %xmm0, %eax239; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rcx240; X64-NOF16C-NEXT: movw %ax, (%rcx)241; X64-NOF16C-NEXT: popq %rax242; X64-NOF16C-NEXT: .cfi_def_cfa_offset 8243; X64-NOF16C-NEXT: retq244;245; X64-F16C-LABEL: double_to_half:246; X64-F16C: # %bb.0:247; X64-F16C-NEXT: pushq %rax248; X64-F16C-NEXT: .cfi_def_cfa_offset 16249; X64-F16C-NEXT: callq __truncdfhf2@PLT250; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax251; X64-F16C-NEXT: vpextrw $0, %xmm0, (%rax)252; X64-F16C-NEXT: popq %rax253; X64-F16C-NEXT: .cfi_def_cfa_offset 8254; X64-F16C-NEXT: retq255 %2 = tail call half @llvm.experimental.constrained.fptrunc.f16.f64(double %0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0256 store half %2, ptr @a, align 2257 ret void258}259 260define void @fp80_to_half(x86_fp80 %0) strictfp {261; X86-NOF16C-LABEL: fp80_to_half:262; X86-NOF16C: # %bb.0:263; X86-NOF16C-NEXT: subl $12, %esp264; X86-NOF16C-NEXT: .cfi_def_cfa_offset 16265; X86-NOF16C-NEXT: fldt {{[0-9]+}}(%esp)266; X86-NOF16C-NEXT: fstpt (%esp)267; X86-NOF16C-NEXT: wait268; X86-NOF16C-NEXT: calll __truncxfhf2269; X86-NOF16C-NEXT: movw %ax, a270; X86-NOF16C-NEXT: addl $12, %esp271; X86-NOF16C-NEXT: .cfi_def_cfa_offset 4272; X86-NOF16C-NEXT: retl273;274; X86-F16C-LABEL: fp80_to_half:275; X86-F16C: # %bb.0:276; X86-F16C-NEXT: subl $12, %esp277; X86-F16C-NEXT: .cfi_def_cfa_offset 16278; X86-F16C-NEXT: fldt {{[0-9]+}}(%esp)279; X86-F16C-NEXT: fstpt (%esp)280; X86-F16C-NEXT: wait281; X86-F16C-NEXT: calll __truncxfhf2282; X86-F16C-NEXT: vpextrw $0, %xmm0, a283; X86-F16C-NEXT: addl $12, %esp284; X86-F16C-NEXT: .cfi_def_cfa_offset 4285; X86-F16C-NEXT: retl286;287; X64-NOF16C-LABEL: fp80_to_half:288; X64-NOF16C: # %bb.0:289; X64-NOF16C-NEXT: subq $24, %rsp290; X64-NOF16C-NEXT: .cfi_def_cfa_offset 32291; X64-NOF16C-NEXT: fldt {{[0-9]+}}(%rsp)292; X64-NOF16C-NEXT: fstpt (%rsp)293; X64-NOF16C-NEXT: wait294; X64-NOF16C-NEXT: callq __truncxfhf2@PLT295; X64-NOF16C-NEXT: pextrw $0, %xmm0, %eax296; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rcx297; X64-NOF16C-NEXT: movw %ax, (%rcx)298; X64-NOF16C-NEXT: addq $24, %rsp299; X64-NOF16C-NEXT: .cfi_def_cfa_offset 8300; X64-NOF16C-NEXT: retq301;302; X64-F16C-LABEL: fp80_to_half:303; X64-F16C: # %bb.0:304; X64-F16C-NEXT: subq $24, %rsp305; X64-F16C-NEXT: .cfi_def_cfa_offset 32306; X64-F16C-NEXT: fldt {{[0-9]+}}(%rsp)307; X64-F16C-NEXT: fstpt (%rsp)308; X64-F16C-NEXT: wait309; X64-F16C-NEXT: callq __truncxfhf2@PLT310; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax311; X64-F16C-NEXT: vpextrw $0, %xmm0, (%rax)312; X64-F16C-NEXT: addq $24, %rsp313; X64-F16C-NEXT: .cfi_def_cfa_offset 8314; X64-F16C-NEXT: retq315 %2 = tail call half @llvm.experimental.constrained.fptrunc.f16.f80(x86_fp80 %0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0316 store half %2, ptr @a, align 2317 ret void318}319 320define void @add() strictfp {321; X86-NOF16C-LABEL: add:322; X86-NOF16C: # %bb.0:323; X86-NOF16C-NEXT: subl $12, %esp324; X86-NOF16C-NEXT: .cfi_def_cfa_offset 16325; X86-NOF16C-NEXT: movzwl a, %eax326; X86-NOF16C-NEXT: movl %eax, (%esp)327; X86-NOF16C-NEXT: calll __extendhfsf2328; X86-NOF16C-NEXT: fstps {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill329; X86-NOF16C-NEXT: wait330; X86-NOF16C-NEXT: movzwl b, %eax331; X86-NOF16C-NEXT: movl %eax, (%esp)332; X86-NOF16C-NEXT: calll __extendhfsf2333; X86-NOF16C-NEXT: flds {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload334; X86-NOF16C-NEXT: faddp %st, %st(1)335; X86-NOF16C-NEXT: fstps (%esp)336; X86-NOF16C-NEXT: wait337; X86-NOF16C-NEXT: calll __truncsfhf2338; X86-NOF16C-NEXT: movw %ax, c339; X86-NOF16C-NEXT: addl $12, %esp340; X86-NOF16C-NEXT: .cfi_def_cfa_offset 4341; X86-NOF16C-NEXT: retl342;343; X86-F16C-LABEL: add:344; X86-F16C: # %bb.0:345; X86-F16C-NEXT: movzwl a, %eax346; X86-F16C-NEXT: vmovd %eax, %xmm0347; X86-F16C-NEXT: vcvtph2ps %xmm0, %xmm0348; X86-F16C-NEXT: movzwl b, %eax349; X86-F16C-NEXT: vmovd %eax, %xmm1350; X86-F16C-NEXT: vcvtph2ps %xmm1, %xmm1351; X86-F16C-NEXT: vaddss %xmm1, %xmm0, %xmm0352; X86-F16C-NEXT: vxorps %xmm1, %xmm1, %xmm1353; X86-F16C-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]354; X86-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0355; X86-F16C-NEXT: vpextrw $0, %xmm0, c356; X86-F16C-NEXT: retl357;358; X64-NOF16C-LABEL: add:359; X64-NOF16C: # %bb.0:360; X64-NOF16C-NEXT: pushq %rax361; X64-NOF16C-NEXT: .cfi_def_cfa_offset 16362; X64-NOF16C-NEXT: movq a@GOTPCREL(%rip), %rax363; X64-NOF16C-NEXT: pinsrw $0, (%rax), %xmm0364; X64-NOF16C-NEXT: callq __extendhfsf2@PLT365; X64-NOF16C-NEXT: movd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Folded Spill366; X64-NOF16C-NEXT: movq b@GOTPCREL(%rip), %rax367; X64-NOF16C-NEXT: pinsrw $0, (%rax), %xmm0368; X64-NOF16C-NEXT: callq __extendhfsf2@PLT369; X64-NOF16C-NEXT: addss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Folded Reload370; X64-NOF16C-NEXT: callq __truncsfhf2@PLT371; X64-NOF16C-NEXT: pextrw $0, %xmm0, %eax372; X64-NOF16C-NEXT: movq c@GOTPCREL(%rip), %rcx373; X64-NOF16C-NEXT: movw %ax, (%rcx)374; X64-NOF16C-NEXT: popq %rax375; X64-NOF16C-NEXT: .cfi_def_cfa_offset 8376; X64-NOF16C-NEXT: retq377;378; X64-F16C-LABEL: add:379; X64-F16C: # %bb.0:380; X64-F16C-NEXT: movq a@GOTPCREL(%rip), %rax381; X64-F16C-NEXT: movzwl (%rax), %eax382; X64-F16C-NEXT: vmovd %eax, %xmm0383; X64-F16C-NEXT: vcvtph2ps %xmm0, %xmm0384; X64-F16C-NEXT: movq b@GOTPCREL(%rip), %rax385; X64-F16C-NEXT: movzwl (%rax), %eax386; X64-F16C-NEXT: vmovd %eax, %xmm1387; X64-F16C-NEXT: vcvtph2ps %xmm1, %xmm1388; X64-F16C-NEXT: vaddss %xmm1, %xmm0, %xmm0389; X64-F16C-NEXT: vxorps %xmm1, %xmm1, %xmm1390; X64-F16C-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]391; X64-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0392; X64-F16C-NEXT: movq c@GOTPCREL(%rip), %rax393; X64-F16C-NEXT: vpextrw $0, %xmm0, (%rax)394; X64-F16C-NEXT: retq395 %1 = load half, ptr @a, align 2396 %2 = tail call float @llvm.experimental.constrained.fpext.f32.f16(half %1, metadata !"fpexcept.strict") #0397 %3 = load half, ptr @b, align 2398 %4 = tail call float @llvm.experimental.constrained.fpext.f32.f16(half %3, metadata !"fpexcept.strict") #0399 %5 = tail call float @llvm.experimental.constrained.fadd.f32(float %2, float %4, metadata !"round.tonearest", metadata !"fpexcept.strict") #0400 %6 = tail call half @llvm.experimental.constrained.fptrunc.f16.f32(float %5, metadata !"round.tonearest", metadata !"fpexcept.strict") #0401 store half %6, ptr @c, align 2402 ret void403}404 405declare float @llvm.experimental.constrained.fpext.f32.f16(half, metadata)406declare double @llvm.experimental.constrained.fpext.f64.f16(half, metadata)407declare x86_fp80 @llvm.experimental.constrained.fpext.f80.f16(half, metadata)408declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)409declare half @llvm.experimental.constrained.fptrunc.f16.f32(float, metadata, metadata)410declare half @llvm.experimental.constrained.fptrunc.f16.f64(double, metadata, metadata)411declare half @llvm.experimental.constrained.fptrunc.f16.f80(x86_fp80, metadata, metadata)412 413attributes #0 = { strictfp }414 415