461 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -mattr=+neon,+fullfp16,+fprcvt -verify-machineinstrs %s -o - | FileCheck %s3; RUN: llc -mattr=+neon -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK-NO-FPRCVT4 5target triple = "aarch64-unknown-linux-gnu"6 7 8; To demonstrate what we have implemented, we'll want a scalar integer value in a SIMD/FP register.9; A common case for this setup is when using the result of an integer reduction intrinsic.10 11; SCVTF12 13define half @scvtf_f16i32(<4 x i32> %x) {14; CHECK-LABEL: scvtf_f16i32:15; CHECK: // %bb.0:16; CHECK-NEXT: scvtf h0, s017; CHECK-NEXT: ret18;19; CHECK-NO-FPRCVT-LABEL: scvtf_f16i32:20; CHECK-NO-FPRCVT: // %bb.0:21; CHECK-NO-FPRCVT-NEXT: scvtf s0, s022; CHECK-NO-FPRCVT-NEXT: fcvt h0, s023; CHECK-NO-FPRCVT-NEXT: ret24 %extract = extractelement <4 x i32> %x, i64 025 %conv = sitofp i32 %extract to half26 ret half %conv27}28 29define half @scvtf_f16i32_neg(<4 x i32> %x) {30; CHECK-LABEL: scvtf_f16i32_neg:31; CHECK: // %bb.0:32; CHECK-NEXT: mov w8, v0.s[1]33; CHECK-NEXT: scvtf h0, w834; CHECK-NEXT: ret35;36; CHECK-NO-FPRCVT-LABEL: scvtf_f16i32_neg:37; CHECK-NO-FPRCVT: // %bb.0:38; CHECK-NO-FPRCVT-NEXT: mov w8, v0.s[1]39; CHECK-NO-FPRCVT-NEXT: scvtf s0, w840; CHECK-NO-FPRCVT-NEXT: fcvt h0, s041; CHECK-NO-FPRCVT-NEXT: ret42 %extract = extractelement <4 x i32> %x, i64 143 %conv = sitofp i32 %extract to half44 ret half %conv45}46 47define <1 x half> @scvtf_f16i32_simple(<1 x i32> %x) {48; CHECK-LABEL: scvtf_f16i32_simple:49; CHECK: // %bb.0:50; CHECK-NEXT: // kill: def $d0 killed $d0 def $q051; CHECK-NEXT: scvtf h0, s052; CHECK-NEXT: ret53;54; CHECK-NO-FPRCVT-LABEL: scvtf_f16i32_simple:55; CHECK-NO-FPRCVT: // %bb.0:56; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q057; CHECK-NO-FPRCVT-NEXT: scvtf s0, s058; CHECK-NO-FPRCVT-NEXT: fcvt h0, s059; CHECK-NO-FPRCVT-NEXT: ret60 %conv = sitofp <1 x i32> %x to <1 x half>61 ret <1 x half> %conv62}63 64define double @scvtf_f64i32(<4 x i32> %x) {65; CHECK-LABEL: scvtf_f64i32:66; CHECK: // %bb.0:67; CHECK-NEXT: scvtf d0, s068; CHECK-NEXT: ret69;70; CHECK-NO-FPRCVT-LABEL: scvtf_f64i32:71; CHECK-NO-FPRCVT: // %bb.0:72; CHECK-NO-FPRCVT-NEXT: fmov w8, s073; CHECK-NO-FPRCVT-NEXT: scvtf d0, w874; CHECK-NO-FPRCVT-NEXT: ret75 %extract = extractelement <4 x i32> %x, i64 076 %conv = sitofp i32 %extract to double77 ret double %conv78}79 80define double @scvtf_f64i32_neg(<4 x i32> %x) {81; CHECK-LABEL: scvtf_f64i32_neg:82; CHECK: // %bb.0:83; CHECK-NEXT: mov w8, v0.s[1]84; CHECK-NEXT: scvtf d0, w885; CHECK-NEXT: ret86;87; CHECK-NO-FPRCVT-LABEL: scvtf_f64i32_neg:88; CHECK-NO-FPRCVT: // %bb.0:89; CHECK-NO-FPRCVT-NEXT: mov w8, v0.s[1]90; CHECK-NO-FPRCVT-NEXT: scvtf d0, w891; CHECK-NO-FPRCVT-NEXT: ret92 %extract = extractelement <4 x i32> %x, i64 193 %conv = sitofp i32 %extract to double94 ret double %conv95}96 97define <1 x double> @scvtf_f64i32_simple(<1 x i32> %x) {98; CHECK-LABEL: scvtf_f64i32_simple:99; CHECK: // %bb.0:100; CHECK-NEXT: scvtf d0, s0101; CHECK-NEXT: ret102;103; CHECK-NO-FPRCVT-LABEL: scvtf_f64i32_simple:104; CHECK-NO-FPRCVT: // %bb.0:105; CHECK-NO-FPRCVT-NEXT: sshll v0.2d, v0.2s, #0106; CHECK-NO-FPRCVT-NEXT: scvtf v0.2d, v0.2d107; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 killed $q0108; CHECK-NO-FPRCVT-NEXT: ret109 %conv = sitofp <1 x i32> %x to <1 x double>110 ret <1 x double> %conv111}112 113define half @scvtf_f16i64(<2 x i64> %x) {114; CHECK-LABEL: scvtf_f16i64:115; CHECK: // %bb.0:116; CHECK-NEXT: scvtf h0, d0117; CHECK-NEXT: ret118;119; CHECK-NO-FPRCVT-LABEL: scvtf_f16i64:120; CHECK-NO-FPRCVT: // %bb.0:121; CHECK-NO-FPRCVT-NEXT: fmov x8, d0122; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8123; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0124; CHECK-NO-FPRCVT-NEXT: ret125 %extract = extractelement <2 x i64> %x, i64 0126 %conv = sitofp i64 %extract to half127 ret half %conv128}129 130define half @scvtf_f16i64_neg(<2 x i64> %x) {131; CHECK-LABEL: scvtf_f16i64_neg:132; CHECK: // %bb.0:133; CHECK-NEXT: mov x8, v0.d[1]134; CHECK-NEXT: scvtf h0, x8135; CHECK-NEXT: ret136;137; CHECK-NO-FPRCVT-LABEL: scvtf_f16i64_neg:138; CHECK-NO-FPRCVT: // %bb.0:139; CHECK-NO-FPRCVT-NEXT: mov x8, v0.d[1]140; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8141; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0142; CHECK-NO-FPRCVT-NEXT: ret143 %extract = extractelement <2 x i64> %x, i64 1144 %conv = sitofp i64 %extract to half145 ret half %conv146}147 148define <1 x half> @scvtf_f16i64_simple(<1 x i64> %x) {149; CHECK-LABEL: scvtf_f16i64_simple:150; CHECK: // %bb.0:151; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0152; CHECK-NEXT: scvtf h0, d0153; CHECK-NEXT: ret154;155; CHECK-NO-FPRCVT-LABEL: scvtf_f16i64_simple:156; CHECK-NO-FPRCVT: // %bb.0:157; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q0158; CHECK-NO-FPRCVT-NEXT: fmov x8, d0159; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8160; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0161; CHECK-NO-FPRCVT-NEXT: ret162 %conv = sitofp <1 x i64> %x to <1 x half>163 ret <1 x half> %conv164}165 166define float @scvtf_f32i64(<2 x i64> %x) {167; CHECK-LABEL: scvtf_f32i64:168; CHECK: // %bb.0:169; CHECK-NEXT: scvtf s0, d0170; CHECK-NEXT: ret171;172; CHECK-NO-FPRCVT-LABEL: scvtf_f32i64:173; CHECK-NO-FPRCVT: // %bb.0:174; CHECK-NO-FPRCVT-NEXT: fmov x8, d0175; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8176; CHECK-NO-FPRCVT-NEXT: ret177 %extract = extractelement <2 x i64> %x, i64 0178 %conv = sitofp i64 %extract to float179 ret float %conv180}181 182define float @scvtf_f32i64_neg(<2 x i64> %x) {183; CHECK-LABEL: scvtf_f32i64_neg:184; CHECK: // %bb.0:185; CHECK-NEXT: mov x8, v0.d[1]186; CHECK-NEXT: scvtf s0, x8187; CHECK-NEXT: ret188;189; CHECK-NO-FPRCVT-LABEL: scvtf_f32i64_neg:190; CHECK-NO-FPRCVT: // %bb.0:191; CHECK-NO-FPRCVT-NEXT: mov x8, v0.d[1]192; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8193; CHECK-NO-FPRCVT-NEXT: ret194 %extract = extractelement <2 x i64> %x, i64 1195 %conv = sitofp i64 %extract to float196 ret float %conv197}198 199; This test does not give the indended result of scvtf s0, d0200; This is due to the input being loaded as a 2 item vector and201; therefore using vector inputs that do not match the pattern202; This test will be fixed in a future revision203define <1 x float> @scvtf_f32i64_simple(<1 x i64> %x) {204; CHECK-LABEL: scvtf_f32i64_simple:205; CHECK: // %bb.0:206; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0207; CHECK-NEXT: movi d1, #0000000000000000208; CHECK-NEXT: scvtf s0, d0209; CHECK-NEXT: mov v1.s[0], v0.s[0]210; CHECK-NEXT: fmov d0, d1211; CHECK-NEXT: ret212;213; CHECK-NO-FPRCVT-LABEL: scvtf_f32i64_simple:214; CHECK-NO-FPRCVT: // %bb.0:215; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q0216; CHECK-NO-FPRCVT-NEXT: fmov x8, d0217; CHECK-NO-FPRCVT-NEXT: movi d1, #0000000000000000218; CHECK-NO-FPRCVT-NEXT: scvtf s0, x8219; CHECK-NO-FPRCVT-NEXT: mov v1.s[0], v0.s[0]220; CHECK-NO-FPRCVT-NEXT: fmov d0, d1221; CHECK-NO-FPRCVT-NEXT: ret222 %conv = sitofp <1 x i64> %x to <1 x float>223 ret <1 x float> %conv224}225 226; UCVTF227 228define half @ucvtf_f16i32(<4 x i32> %x) {229; CHECK-LABEL: ucvtf_f16i32:230; CHECK: // %bb.0:231; CHECK-NEXT: ucvtf h0, s0232; CHECK-NEXT: ret233;234; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i32:235; CHECK-NO-FPRCVT: // %bb.0:236; CHECK-NO-FPRCVT-NEXT: ucvtf s0, s0237; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0238; CHECK-NO-FPRCVT-NEXT: ret239 %extract = extractelement <4 x i32> %x, i64 0240 %conv = uitofp i32 %extract to half241 ret half %conv242}243 244define half @ucvtf_f16i32_neg(<4 x i32> %x) {245; CHECK-LABEL: ucvtf_f16i32_neg:246; CHECK: // %bb.0:247; CHECK-NEXT: mov w8, v0.s[1]248; CHECK-NEXT: ucvtf h0, w8249; CHECK-NEXT: ret250;251; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i32_neg:252; CHECK-NO-FPRCVT: // %bb.0:253; CHECK-NO-FPRCVT-NEXT: mov w8, v0.s[1]254; CHECK-NO-FPRCVT-NEXT: ucvtf s0, w8255; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0256; CHECK-NO-FPRCVT-NEXT: ret257 %extract = extractelement <4 x i32> %x, i64 1258 %conv = uitofp i32 %extract to half259 ret half %conv260}261 262define <1 x half> @ucvtf_f16i32_simple(<1 x i32> %x) {263; CHECK-LABEL: ucvtf_f16i32_simple:264; CHECK: // %bb.0:265; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0266; CHECK-NEXT: ucvtf h0, s0267; CHECK-NEXT: ret268;269; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i32_simple:270; CHECK-NO-FPRCVT: // %bb.0:271; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q0272; CHECK-NO-FPRCVT-NEXT: ucvtf s0, s0273; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0274; CHECK-NO-FPRCVT-NEXT: ret275 %conv = uitofp <1 x i32> %x to <1 x half>276 ret <1 x half> %conv277}278 279define double @ucvtf_f64i32(<4 x i32> %x) {280; CHECK-LABEL: ucvtf_f64i32:281; CHECK: // %bb.0:282; CHECK-NEXT: ucvtf d0, s0283; CHECK-NEXT: ret284;285; CHECK-NO-FPRCVT-LABEL: ucvtf_f64i32:286; CHECK-NO-FPRCVT: // %bb.0:287; CHECK-NO-FPRCVT-NEXT: fmov w8, s0288; CHECK-NO-FPRCVT-NEXT: ucvtf d0, w8289; CHECK-NO-FPRCVT-NEXT: ret290 %extract = extractelement <4 x i32> %x, i64 0291 %conv = uitofp i32 %extract to double292 ret double %conv293}294 295define double @ucvtf_f64i32_neg(<4 x i32> %x) {296; CHECK-LABEL: ucvtf_f64i32_neg:297; CHECK: // %bb.0:298; CHECK-NEXT: mov w8, v0.s[1]299; CHECK-NEXT: ucvtf d0, w8300; CHECK-NEXT: ret301;302; CHECK-NO-FPRCVT-LABEL: ucvtf_f64i32_neg:303; CHECK-NO-FPRCVT: // %bb.0:304; CHECK-NO-FPRCVT-NEXT: mov w8, v0.s[1]305; CHECK-NO-FPRCVT-NEXT: ucvtf d0, w8306; CHECK-NO-FPRCVT-NEXT: ret307 %extract = extractelement <4 x i32> %x, i64 1308 %conv = uitofp i32 %extract to double309 ret double %conv310}311 312define <1 x double> @ucvtf_f64i32_simple(<1 x i32> %x) {313; CHECK-LABEL: ucvtf_f64i32_simple:314; CHECK: // %bb.0:315; CHECK-NEXT: ucvtf d0, s0316; CHECK-NEXT: ret317;318; CHECK-NO-FPRCVT-LABEL: ucvtf_f64i32_simple:319; CHECK-NO-FPRCVT: // %bb.0:320; CHECK-NO-FPRCVT-NEXT: ushll v0.2d, v0.2s, #0321; CHECK-NO-FPRCVT-NEXT: ucvtf v0.2d, v0.2d322; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 killed $q0323; CHECK-NO-FPRCVT-NEXT: ret324 %conv = uitofp <1 x i32> %x to <1 x double>325 ret <1 x double> %conv326}327 328define half @ucvtf_f16i64(<2 x i64> %x) {329; CHECK-LABEL: ucvtf_f16i64:330; CHECK: // %bb.0:331; CHECK-NEXT: ucvtf h0, d0332; CHECK-NEXT: ret333;334; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i64:335; CHECK-NO-FPRCVT: // %bb.0:336; CHECK-NO-FPRCVT-NEXT: fmov x8, d0337; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8338; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0339; CHECK-NO-FPRCVT-NEXT: ret340 %extract = extractelement <2 x i64> %x, i64 0341 %conv = uitofp i64 %extract to half342 ret half %conv343}344 345define half @ucvtf_f16i64_neg(<2 x i64> %x) {346; CHECK-LABEL: ucvtf_f16i64_neg:347; CHECK: // %bb.0:348; CHECK-NEXT: mov x8, v0.d[1]349; CHECK-NEXT: ucvtf h0, x8350; CHECK-NEXT: ret351;352; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i64_neg:353; CHECK-NO-FPRCVT: // %bb.0:354; CHECK-NO-FPRCVT-NEXT: mov x8, v0.d[1]355; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8356; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0357; CHECK-NO-FPRCVT-NEXT: ret358 %extract = extractelement <2 x i64> %x, i64 1359 %conv = uitofp i64 %extract to half360 ret half %conv361}362 363define <1 x half> @ucvtf_f16i64_simple(<1 x i64> %x) {364; CHECK-LABEL: ucvtf_f16i64_simple:365; CHECK: // %bb.0:366; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0367; CHECK-NEXT: ucvtf h0, d0368; CHECK-NEXT: ret369;370; CHECK-NO-FPRCVT-LABEL: ucvtf_f16i64_simple:371; CHECK-NO-FPRCVT: // %bb.0:372; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q0373; CHECK-NO-FPRCVT-NEXT: fmov x8, d0374; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8375; CHECK-NO-FPRCVT-NEXT: fcvt h0, s0376; CHECK-NO-FPRCVT-NEXT: ret377 %conv = uitofp <1 x i64> %x to <1 x half>378 ret <1 x half> %conv379}380 381define float @ucvtf_f32i64(<2 x i64> %x) {382; CHECK-LABEL: ucvtf_f32i64:383; CHECK: // %bb.0:384; CHECK-NEXT: ucvtf s0, d0385; CHECK-NEXT: ret386;387; CHECK-NO-FPRCVT-LABEL: ucvtf_f32i64:388; CHECK-NO-FPRCVT: // %bb.0:389; CHECK-NO-FPRCVT-NEXT: fmov x8, d0390; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8391; CHECK-NO-FPRCVT-NEXT: ret392 %extract = extractelement <2 x i64> %x, i64 0393 %conv = uitofp i64 %extract to float394 ret float %conv395}396 397define float @ucvtf_f32i64_neg(<2 x i64> %x) {398; CHECK-LABEL: ucvtf_f32i64_neg:399; CHECK: // %bb.0:400; CHECK-NEXT: mov x8, v0.d[1]401; CHECK-NEXT: ucvtf s0, x8402; CHECK-NEXT: ret403;404; CHECK-NO-FPRCVT-LABEL: ucvtf_f32i64_neg:405; CHECK-NO-FPRCVT: // %bb.0:406; CHECK-NO-FPRCVT-NEXT: mov x8, v0.d[1]407; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8408; CHECK-NO-FPRCVT-NEXT: ret409 %extract = extractelement <2 x i64> %x, i64 1410 %conv = uitofp i64 %extract to float411 ret float %conv412}413 414; This test does not give the indended result of ucvtf s0, d0415; This is due to the input being loaded as a 2 item vector and416; therefore using vector inputs that do not match the pattern417; This test will be fixed in a future revision418define <1 x float> @ucvtf_f32i64_simple(<1 x i64> %x) {419; CHECK-LABEL: ucvtf_f32i64_simple:420; CHECK: // %bb.0:421; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0422; CHECK-NEXT: movi d1, #0000000000000000423; CHECK-NEXT: ucvtf s0, d0424; CHECK-NEXT: mov v1.s[0], v0.s[0]425; CHECK-NEXT: fmov d0, d1426; CHECK-NEXT: ret427;428; CHECK-NO-FPRCVT-LABEL: ucvtf_f32i64_simple:429; CHECK-NO-FPRCVT: // %bb.0:430; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 def $q0431; CHECK-NO-FPRCVT-NEXT: fmov x8, d0432; CHECK-NO-FPRCVT-NEXT: movi d1, #0000000000000000433; CHECK-NO-FPRCVT-NEXT: ucvtf s0, x8434; CHECK-NO-FPRCVT-NEXT: mov v1.s[0], v0.s[0]435; CHECK-NO-FPRCVT-NEXT: fmov d0, d1436; CHECK-NO-FPRCVT-NEXT: ret437 %conv = uitofp <1 x i64> %x to <1 x float>438 ret <1 x float> %conv439}440 441define <1 x double> @uitofp_sext_v2i32_extract_lane0(<2 x i32> %x) {442; CHECK-LABEL: uitofp_sext_v2i32_extract_lane0:443; CHECK: // %bb.0:444; CHECK-NEXT: sshll v0.2d, v0.2s, #0445; CHECK-NEXT: ucvtf v0.2d, v0.2d446; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0447; CHECK-NEXT: ret448;449; CHECK-NO-FPRCVT-LABEL: uitofp_sext_v2i32_extract_lane0:450; CHECK-NO-FPRCVT: // %bb.0:451; CHECK-NO-FPRCVT-NEXT: sshll v0.2d, v0.2s, #0452; CHECK-NO-FPRCVT-NEXT: ucvtf v0.2d, v0.2d453; CHECK-NO-FPRCVT-NEXT: // kill: def $d0 killed $d0 killed $q0454; CHECK-NO-FPRCVT-NEXT: ret455 %wide = sext <2 x i32> %x to <2 x i64>456 %fpv2 = uitofp <2 x i64> %wide to <2 x double>457 %lane0 = shufflevector <2 x double> %fpv2, <2 x double> poison, <1 x i32> zeroinitializer458 ret <1 x double> %lane0459}460 461