1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,SSE2 3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE,SSE41 4; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX1 5 6define float @trunc_unsigned_f32(float %x) #0 { 7; SSE2-LABEL: trunc_unsigned_f32: 8; SSE2: # %bb.0: 9; SSE2-NEXT: cvttss2si %xmm0, %rax 10; SSE2-NEXT: movl %eax, %eax 11; SSE2-NEXT: xorps %xmm0, %xmm0 12; SSE2-NEXT: cvtsi2ss %rax, %xmm0 13; SSE2-NEXT: retq 14; 15; SSE41-LABEL: trunc_unsigned_f32: 16; SSE41: # %bb.0: 17; SSE41-NEXT: roundss $11, %xmm0, %xmm0 18; SSE41-NEXT: retq 19; 20; AVX1-LABEL: trunc_unsigned_f32: 21; AVX1: # %bb.0: 22; AVX1-NEXT: vroundss $11, %xmm0, %xmm0, %xmm0 23; AVX1-NEXT: retq 24 %i = fptoui float %x to i32 25 %r = uitofp i32 %i to float 26 ret float %r 27} 28 29define double @trunc_unsigned_f64(double %x) #0 { 30; SSE2-LABEL: trunc_unsigned_f64: 31; SSE2: # %bb.0: 32; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero 33; SSE2-NEXT: movapd %xmm0, %xmm2 34; SSE2-NEXT: subsd %xmm1, %xmm2 35; SSE2-NEXT: cvttsd2si %xmm2, %rax 36; SSE2-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000 37; SSE2-NEXT: xorq %rax, %rcx 38; SSE2-NEXT: cvttsd2si %xmm0, %rax 39; SSE2-NEXT: ucomisd %xmm1, %xmm0 40; SSE2-NEXT: cmovaeq %rcx, %rax 41; SSE2-NEXT: movq %rax, %xmm1 42; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],mem[0],xmm1[1],mem[1] 43; SSE2-NEXT: subpd {{.*}}(%rip), %xmm1 44; SSE2-NEXT: movapd %xmm1, %xmm0 45; SSE2-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1],xmm1[1] 46; SSE2-NEXT: addsd %xmm1, %xmm0 47; SSE2-NEXT: retq 48; 49; SSE41-LABEL: trunc_unsigned_f64: 50; SSE41: # %bb.0: 51; SSE41-NEXT: roundsd $11, %xmm0, %xmm0 52; SSE41-NEXT: retq 53; 54; AVX1-LABEL: trunc_unsigned_f64: 55; AVX1: # %bb.0: 56; AVX1-NEXT: vroundsd $11, %xmm0, %xmm0, %xmm0 57; AVX1-NEXT: retq 58 %i = fptoui double %x to i64 59 %r = uitofp i64 %i to double 60 ret double %r 61} 62 63define <4 x float> @trunc_unsigned_v4f32(<4 x float> %x) #0 { 64; SSE2-LABEL: trunc_unsigned_v4f32: 65; SSE2: # %bb.0: 66; SSE2-NEXT: movaps {{.*#+}} xmm2 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9] 67; SSE2-NEXT: movaps %xmm0, %xmm1 68; SSE2-NEXT: cmpltps %xmm2, %xmm1 69; SSE2-NEXT: cvttps2dq %xmm0, %xmm3 70; SSE2-NEXT: subps %xmm2, %xmm0 71; SSE2-NEXT: cvttps2dq %xmm0, %xmm0 72; SSE2-NEXT: xorps {{.*}}(%rip), %xmm0 73; SSE2-NEXT: andps %xmm1, %xmm3 74; SSE2-NEXT: andnps %xmm0, %xmm1 75; SSE2-NEXT: orps %xmm3, %xmm1 76; SSE2-NEXT: movaps {{.*#+}} xmm0 = [65535,65535,65535,65535] 77; SSE2-NEXT: andps %xmm1, %xmm0 78; SSE2-NEXT: orps {{.*}}(%rip), %xmm0 79; SSE2-NEXT: psrld $16, %xmm1 80; SSE2-NEXT: por {{.*}}(%rip), %xmm1 81; SSE2-NEXT: subps {{.*}}(%rip), %xmm1 82; SSE2-NEXT: addps %xmm0, %xmm1 83; SSE2-NEXT: movaps %xmm1, %xmm0 84; SSE2-NEXT: retq 85; 86; SSE41-LABEL: trunc_unsigned_v4f32: 87; SSE41: # %bb.0: 88; SSE41-NEXT: roundps $11, %xmm0, %xmm0 89; SSE41-NEXT: retq 90; 91; AVX1-LABEL: trunc_unsigned_v4f32: 92; AVX1: # %bb.0: 93; AVX1-NEXT: vroundps $11, %xmm0, %xmm0 94; AVX1-NEXT: retq 95 %i = fptoui <4 x float> %x to <4 x i32> 96 %r = uitofp <4 x i32> %i to <4 x float> 97 ret <4 x float> %r 98} 99 100define <2 x double> @trunc_unsigned_v2f64(<2 x double> %x) #0 { 101; SSE2-LABEL: trunc_unsigned_v2f64: 102; SSE2: # %bb.0: 103; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero 104; SSE2-NEXT: movapd %xmm0, %xmm1 105; SSE2-NEXT: subsd %xmm2, %xmm1 106; SSE2-NEXT: cvttsd2si %xmm1, %rax 107; SSE2-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000 108; SSE2-NEXT: xorq %rcx, %rax 109; SSE2-NEXT: cvttsd2si %xmm0, %rdx 110; SSE2-NEXT: ucomisd %xmm2, %xmm0 111; SSE2-NEXT: cmovaeq %rax, %rdx 112; SSE2-NEXT: movq %rdx, %xmm1 113; SSE2-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1] 114; SSE2-NEXT: movapd %xmm0, %xmm3 115; SSE2-NEXT: subsd %xmm2, %xmm3 116; SSE2-NEXT: cvttsd2si %xmm3, %rax 117; SSE2-NEXT: xorq %rcx, %rax 118; SSE2-NEXT: cvttsd2si %xmm0, %rcx 119; SSE2-NEXT: ucomisd %xmm2, %xmm0 120; SSE2-NEXT: cmovaeq %rax, %rcx 121; SSE2-NEXT: movq %rcx, %xmm0 122; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] 123; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [4294967295,4294967295] 124; SSE2-NEXT: pand %xmm1, %xmm0 125; SSE2-NEXT: por {{.*}}(%rip), %xmm0 126; SSE2-NEXT: psrlq $32, %xmm1 127; SSE2-NEXT: por {{.*}}(%rip), %xmm1 128; SSE2-NEXT: subpd {{.*}}(%rip), %xmm1 129; SSE2-NEXT: addpd %xmm0, %xmm1 130; SSE2-NEXT: movapd %xmm1, %xmm0 131; SSE2-NEXT: retq 132; 133; SSE41-LABEL: trunc_unsigned_v2f64: 134; SSE41: # %bb.0: 135; SSE41-NEXT: roundpd $11, %xmm0, %xmm0 136; SSE41-NEXT: retq 137; 138; AVX1-LABEL: trunc_unsigned_v2f64: 139; AVX1: # %bb.0: 140; AVX1-NEXT: vroundpd $11, %xmm0, %xmm0 141; AVX1-NEXT: retq 142 %i = fptoui <2 x double> %x to <2 x i64> 143 %r = uitofp <2 x i64> %i to <2 x double> 144 ret <2 x double> %r 145} 146 147define <4 x double> @trunc_unsigned_v4f64(<4 x double> %x) #0 { 148; SSE2-LABEL: trunc_unsigned_v4f64: 149; SSE2: # %bb.0: 150; SSE2-NEXT: movapd %xmm1, %xmm2 151; SSE2-NEXT: movsd {{.*#+}} xmm3 = mem[0],zero 152; SSE2-NEXT: subsd %xmm3, %xmm1 153; SSE2-NEXT: cvttsd2si %xmm1, %rcx 154; SSE2-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 155; SSE2-NEXT: xorq %rax, %rcx 156; SSE2-NEXT: cvttsd2si %xmm2, %rdx 157; SSE2-NEXT: ucomisd %xmm3, %xmm2 158; SSE2-NEXT: cmovaeq %rcx, %rdx 159; SSE2-NEXT: movq %rdx, %xmm1 160; SSE2-NEXT: unpckhpd {{.*#+}} xmm2 = xmm2[1,1] 161; SSE2-NEXT: movapd %xmm2, %xmm4 162; SSE2-NEXT: subsd %xmm3, %xmm4 163; SSE2-NEXT: cvttsd2si %xmm4, %rcx 164; SSE2-NEXT: xorq %rax, %rcx 165; SSE2-NEXT: cvttsd2si %xmm2, %rdx 166; SSE2-NEXT: ucomisd %xmm3, %xmm2 167; SSE2-NEXT: cmovaeq %rcx, %rdx 168; SSE2-NEXT: movq %rdx, %xmm2 169; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0] 170; SSE2-NEXT: movapd %xmm0, %xmm2 171; SSE2-NEXT: subsd %xmm3, %xmm2 172; SSE2-NEXT: cvttsd2si %xmm2, %rcx 173; SSE2-NEXT: xorq %rax, %rcx 174; SSE2-NEXT: cvttsd2si %xmm0, %rdx 175; SSE2-NEXT: ucomisd %xmm3, %xmm0 176; SSE2-NEXT: cmovaeq %rcx, %rdx 177; SSE2-NEXT: movq %rdx, %xmm2 178; SSE2-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1] 179; SSE2-NEXT: movapd %xmm0, %xmm4 180; SSE2-NEXT: subsd %xmm3, %xmm4 181; SSE2-NEXT: cvttsd2si %xmm4, %rcx 182; SSE2-NEXT: xorq %rax, %rcx 183; SSE2-NEXT: cvttsd2si %xmm0, %rax 184; SSE2-NEXT: ucomisd %xmm3, %xmm0 185; SSE2-NEXT: cmovaeq %rcx, %rax 186; SSE2-NEXT: movq %rax, %xmm0 187; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0] 188; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [4294967295,4294967295] 189; SSE2-NEXT: movdqa %xmm2, %xmm3 190; SSE2-NEXT: pand %xmm0, %xmm3 191; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [4841369599423283200,4841369599423283200] 192; SSE2-NEXT: por %xmm4, %xmm3 193; SSE2-NEXT: psrlq $32, %xmm2 194; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [4985484787499139072,4985484787499139072] 195; SSE2-NEXT: por %xmm5, %xmm2 196; SSE2-NEXT: movapd {{.*#+}} xmm6 = [1.9342813118337666E+25,1.9342813118337666E+25] 197; SSE2-NEXT: subpd %xmm6, %xmm2 198; SSE2-NEXT: addpd %xmm3, %xmm2 199; SSE2-NEXT: pand %xmm1, %xmm0 200; SSE2-NEXT: por %xmm4, %xmm0 201; SSE2-NEXT: psrlq $32, %xmm1 202; SSE2-NEXT: por %xmm5, %xmm1 203; SSE2-NEXT: subpd %xmm6, %xmm1 204; SSE2-NEXT: addpd %xmm0, %xmm1 205; SSE2-NEXT: movapd %xmm2, %xmm0 206; SSE2-NEXT: retq 207; 208; SSE41-LABEL: trunc_unsigned_v4f64: 209; SSE41: # %bb.0: 210; SSE41-NEXT: roundpd $11, %xmm0, %xmm0 211; SSE41-NEXT: roundpd $11, %xmm1, %xmm1 212; SSE41-NEXT: retq 213; 214; AVX1-LABEL: trunc_unsigned_v4f64: 215; AVX1: # %bb.0: 216; AVX1-NEXT: vroundpd $11, %ymm0, %ymm0 217; AVX1-NEXT: retq 218 %i = fptoui <4 x double> %x to <4 x i64> 219 %r = uitofp <4 x i64> %i to <4 x double> 220 ret <4 x double> %r 221} 222 223define float @trunc_signed_f32_no_fast_math(float %x) { 224; SSE-LABEL: trunc_signed_f32_no_fast_math: 225; SSE: # %bb.0: 226; SSE-NEXT: cvttps2dq %xmm0, %xmm0 227; SSE-NEXT: cvtdq2ps %xmm0, %xmm0 228; SSE-NEXT: retq 229; 230; AVX1-LABEL: trunc_signed_f32_no_fast_math: 231; AVX1: # %bb.0: 232; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0 233; AVX1-NEXT: vcvtdq2ps %xmm0, %xmm0 234; AVX1-NEXT: retq 235 %i = fptosi float %x to i32 236 %r = sitofp i32 %i to float 237 ret float %r 238} 239 240define float @trunc_signed_f32(float %x) #0 { 241; SSE2-LABEL: trunc_signed_f32: 242; SSE2: # %bb.0: 243; SSE2-NEXT: cvttps2dq %xmm0, %xmm0 244; SSE2-NEXT: cvtdq2ps %xmm0, %xmm0 245; SSE2-NEXT: retq 246; 247; SSE41-LABEL: trunc_signed_f32: 248; SSE41: # %bb.0: 249; SSE41-NEXT: roundss $11, %xmm0, %xmm0 250; SSE41-NEXT: retq 251; 252; AVX1-LABEL: trunc_signed_f32: 253; AVX1: # %bb.0: 254; AVX1-NEXT: vroundss $11, %xmm0, %xmm0, %xmm0 255; AVX1-NEXT: retq 256 %i = fptosi float %x to i32 257 %r = sitofp i32 %i to float 258 ret float %r 259} 260 261define double @trunc_signed_f64(double %x) #0 { 262; SSE2-LABEL: trunc_signed_f64: 263; SSE2: # %bb.0: 264; SSE2-NEXT: cvttsd2si %xmm0, %rax 265; SSE2-NEXT: xorps %xmm0, %xmm0 266; SSE2-NEXT: cvtsi2sd %rax, %xmm0 267; SSE2-NEXT: retq 268; 269; SSE41-LABEL: trunc_signed_f64: 270; SSE41: # %bb.0: 271; SSE41-NEXT: roundsd $11, %xmm0, %xmm0 272; SSE41-NEXT: retq 273; 274; AVX1-LABEL: trunc_signed_f64: 275; AVX1: # %bb.0: 276; AVX1-NEXT: vroundsd $11, %xmm0, %xmm0, %xmm0 277; AVX1-NEXT: retq 278 %i = fptosi double %x to i64 279 %r = sitofp i64 %i to double 280 ret double %r 281} 282 283define <4 x float> @trunc_signed_v4f32(<4 x float> %x) #0 { 284; SSE2-LABEL: trunc_signed_v4f32: 285; SSE2: # %bb.0: 286; SSE2-NEXT: cvttps2dq %xmm0, %xmm0 287; SSE2-NEXT: cvtdq2ps %xmm0, %xmm0 288; SSE2-NEXT: retq 289; 290; SSE41-LABEL: trunc_signed_v4f32: 291; SSE41: # %bb.0: 292; SSE41-NEXT: roundps $11, %xmm0, %xmm0 293; SSE41-NEXT: retq 294; 295; AVX1-LABEL: trunc_signed_v4f32: 296; AVX1: # %bb.0: 297; AVX1-NEXT: vroundps $11, %xmm0, %xmm0 298; AVX1-NEXT: retq 299 %i = fptosi <4 x float> %x to <4 x i32> 300 %r = sitofp <4 x i32> %i to <4 x float> 301 ret <4 x float> %r 302} 303 304define <2 x double> @trunc_signed_v2f64(<2 x double> %x) #0 { 305; SSE2-LABEL: trunc_signed_v2f64: 306; SSE2: # %bb.0: 307; SSE2-NEXT: cvttsd2si %xmm0, %rax 308; SSE2-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1] 309; SSE2-NEXT: cvttsd2si %xmm0, %rcx 310; SSE2-NEXT: xorps %xmm0, %xmm0 311; SSE2-NEXT: cvtsi2sd %rax, %xmm0 312; SSE2-NEXT: cvtsi2sd %rcx, %xmm1 313; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] 314; SSE2-NEXT: retq 315; 316; SSE41-LABEL: trunc_signed_v2f64: 317; SSE41: # %bb.0: 318; SSE41-NEXT: roundpd $11, %xmm0, %xmm0 319; SSE41-NEXT: retq 320; 321; AVX1-LABEL: trunc_signed_v2f64: 322; AVX1: # %bb.0: 323; AVX1-NEXT: vroundpd $11, %xmm0, %xmm0 324; AVX1-NEXT: retq 325 %i = fptosi <2 x double> %x to <2 x i64> 326 %r = sitofp <2 x i64> %i to <2 x double> 327 ret <2 x double> %r 328} 329 330define <4 x double> @trunc_signed_v4f64(<4 x double> %x) #0 { 331; SSE2-LABEL: trunc_signed_v4f64: 332; SSE2: # %bb.0: 333; SSE2-NEXT: cvttsd2si %xmm1, %rax 334; SSE2-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1,1] 335; SSE2-NEXT: cvttsd2si %xmm1, %rcx 336; SSE2-NEXT: cvttsd2si %xmm0, %rdx 337; SSE2-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1] 338; SSE2-NEXT: cvttsd2si %xmm0, %rsi 339; SSE2-NEXT: xorps %xmm0, %xmm0 340; SSE2-NEXT: cvtsi2sd %rdx, %xmm0 341; SSE2-NEXT: xorps %xmm1, %xmm1 342; SSE2-NEXT: cvtsi2sd %rsi, %xmm1 343; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] 344; SSE2-NEXT: xorps %xmm1, %xmm1 345; SSE2-NEXT: cvtsi2sd %rax, %xmm1 346; SSE2-NEXT: cvtsi2sd %rcx, %xmm2 347; SSE2-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] 348; SSE2-NEXT: retq 349; 350; SSE41-LABEL: trunc_signed_v4f64: 351; SSE41: # %bb.0: 352; SSE41-NEXT: roundpd $11, %xmm0, %xmm0 353; SSE41-NEXT: roundpd $11, %xmm1, %xmm1 354; SSE41-NEXT: retq 355; 356; AVX1-LABEL: trunc_signed_v4f64: 357; AVX1: # %bb.0: 358; AVX1-NEXT: vroundpd $11, %ymm0, %ymm0 359; AVX1-NEXT: retq 360 %i = fptosi <4 x double> %x to <4 x i64> 361 %r = sitofp <4 x i64> %i to <4 x double> 362 ret <4 x double> %r 363} 364 365; The fold may be guarded to allow existing code to continue 366; working based on its assumptions of float->int overflow. 367 368define float @trunc_unsigned_f32_disable_via_attr(float %x) #1 { 369; SSE-LABEL: trunc_unsigned_f32_disable_via_attr: 370; SSE: # %bb.0: 371; SSE-NEXT: cvttss2si %xmm0, %rax 372; SSE-NEXT: movl %eax, %eax 373; SSE-NEXT: xorps %xmm0, %xmm0 374; SSE-NEXT: cvtsi2ss %rax, %xmm0 375; SSE-NEXT: retq 376; 377; AVX1-LABEL: trunc_unsigned_f32_disable_via_attr: 378; AVX1: # %bb.0: 379; AVX1-NEXT: vcvttss2si %xmm0, %rax 380; AVX1-NEXT: movl %eax, %eax 381; AVX1-NEXT: vcvtsi2ss %rax, %xmm1, %xmm0 382; AVX1-NEXT: retq 383 %i = fptoui float %x to i32 384 %r = uitofp i32 %i to float 385 ret float %r 386} 387 388define double @trunc_signed_f64_disable_via_attr(double %x) #1 { 389; SSE-LABEL: trunc_signed_f64_disable_via_attr: 390; SSE: # %bb.0: 391; SSE-NEXT: cvttsd2si %xmm0, %rax 392; SSE-NEXT: xorps %xmm0, %xmm0 393; SSE-NEXT: cvtsi2sd %rax, %xmm0 394; SSE-NEXT: retq 395; 396; AVX1-LABEL: trunc_signed_f64_disable_via_attr: 397; AVX1: # %bb.0: 398; AVX1-NEXT: vcvttsd2si %xmm0, %rax 399; AVX1-NEXT: vcvtsi2sd %rax, %xmm1, %xmm0 400; AVX1-NEXT: retq 401 %i = fptosi double %x to i64 402 %r = sitofp i64 %i to double 403 ret double %r 404} 405 406attributes #0 = { nounwind "no-signed-zeros-fp-math"="true" } 407attributes #1 = { nounwind "no-signed-zeros-fp-math"="true" "strict-float-cast-overflow"="false" } 408