1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -O2 -mtriple=x86_64-linux-android -mattr=+mmx | FileCheck %s --check-prefix=X64 3; RUN: llc < %s -O2 -mtriple=x86_64-linux-gnu -mattr=+mmx | FileCheck %s --check-prefix=X64 4; RUN: llc < %s -O2 -mtriple=x86_64-linux-gnu -mattr=-mmx | FileCheck %s --check-prefix=X64_NO_MMX 5; RUN: llc < %s -O2 -mtriple=i686-linux-gnu -mattr=+mmx | FileCheck %s --check-prefix=X32 6 7; Check soft floating point conversion function calls. 8 9@vi32 = common global i32 0, align 4 10@vi64 = common global i64 0, align 8 11@vu32 = common global i32 0, align 4 12@vu64 = common global i64 0, align 8 13@vf32 = common global float 0.000000e+00, align 4 14@vf64 = common global double 0.000000e+00, align 8 15@vf80 = common global x86_fp80 0xK00000000000000000000, align 8 16@vf128 = common global fp128 0xL00000000000000000000000000000000, align 16 17 18define void @TestFPExtF32_F128() { 19entry: 20 %0 = load float, float* @vf32, align 4 21 %conv = fpext float %0 to fp128 22 store fp128 %conv, fp128* @vf128, align 16 23 ret void 24; X32-LABEL: TestFPExtF32_F128: 25; X32: flds vf32 26; X32: fstps 27; X32: calll __extendsftf2 28; X32: retl 29; 30; X64-LABEL: TestFPExtF32_F128: 31; X64: movss vf32(%rip), %xmm0 32; X64-NEXT: callq __extendsftf2 33; X64-NEXT: movaps %xmm0, vf128(%rip) 34; X64: retq 35} 36 37define void @TestFPExtF64_F128() { 38entry: 39 %0 = load double, double* @vf64, align 8 40 %conv = fpext double %0 to fp128 41 store fp128 %conv, fp128* @vf128, align 16 42 ret void 43; X32-LABEL: TestFPExtF64_F128: 44; X32: fldl vf64 45; X32: fstpl 46; X32: calll __extenddftf2 47; X32: retl 48; 49; X64-LABEL: TestFPExtF64_F128: 50; X64: movsd vf64(%rip), %xmm0 51; X64-NEXT: callq __extenddftf2 52; X64-NEXT: movaps %xmm0, vf128(%rip) 53; X64: ret 54} 55 56define void @TestFPExtF80_F128() { 57entry: 58 %0 = load x86_fp80, x86_fp80* @vf80, align 8 59 %conv = fpext x86_fp80 %0 to fp128 60 store fp128 %conv, fp128* @vf128, align 16 61 ret void 62; X32-LABEL: TestFPExtF80_F128: 63; X32: calll __extendxftf2 64; 65; X64-LABEL: TestFPExtF80_F128: 66; X64: callq __extendxftf2 67} 68 69define void @TestFPToSIF128_I32() { 70entry: 71 %0 = load fp128, fp128* @vf128, align 16 72 %conv = fptosi fp128 %0 to i32 73 store i32 %conv, i32* @vi32, align 4 74 ret void 75; X32-LABEL: TestFPToSIF128_I32: 76; X32: calll __fixtfsi 77; X32: retl 78; 79; X64-LABEL: TestFPToSIF128_I32: 80; X64: movaps vf128(%rip), %xmm0 81; X64-NEXT: callq __fixtfsi 82; X64-NEXT: movl %eax, vi32(%rip) 83; X64: retq 84} 85 86define void @TestFPToUIF128_U32() { 87entry: 88 %0 = load fp128, fp128* @vf128, align 16 89 %conv = fptoui fp128 %0 to i32 90 store i32 %conv, i32* @vu32, align 4 91 ret void 92; X32-LABEL: TestFPToUIF128_U32: 93; X32: calll __fixunstfsi 94; X32: retl 95; 96; X64-LABEL: TestFPToUIF128_U32: 97; X64: movaps vf128(%rip), %xmm0 98; X64-NEXT: callq __fixunstfsi 99; X64-NEXT: movl %eax, vu32(%rip) 100; X64: retq 101} 102 103define void @TestFPToSIF128_I64() { 104entry: 105 %0 = load fp128, fp128* @vf128, align 16 106 %conv = fptosi fp128 %0 to i32 107 %conv1 = sext i32 %conv to i64 108 store i64 %conv1, i64* @vi64, align 8 109 ret void 110; X32-LABEL: TestFPToSIF128_I64: 111; X32: calll __fixtfsi 112; X32: retl 113; 114; X64-LABEL: TestFPToSIF128_I64: 115; X64: movaps vf128(%rip), %xmm0 116; X64-NEXT: callq __fixtfsi 117; X64-NEXT: cltq 118; X64-NEXT: movq %rax, vi64(%rip) 119; X64: retq 120} 121 122define void @TestFPToUIF128_U64() { 123entry: 124 %0 = load fp128, fp128* @vf128, align 16 125 %conv = fptoui fp128 %0 to i32 126 %conv1 = zext i32 %conv to i64 127 store i64 %conv1, i64* @vu64, align 8 128 ret void 129; X32-LABEL: TestFPToUIF128_U64: 130; X32: calll __fixunstfsi 131; X32: retl 132; 133; X64-LABEL: TestFPToUIF128_U64: 134; X64: movaps vf128(%rip), %xmm0 135; X64-NEXT: callq __fixunstfsi 136; X64-NEXT: movl %eax, %eax 137; X64-NEXT: movq %rax, vu64(%rip) 138; X64: retq 139} 140 141define void @TestFPTruncF128_F32() { 142entry: 143 %0 = load fp128, fp128* @vf128, align 16 144 %conv = fptrunc fp128 %0 to float 145 store float %conv, float* @vf32, align 4 146 ret void 147; X32-LABEL: TestFPTruncF128_F32: 148; X32: calll __trunctfsf2 149; X32: fstps vf32 150; X32: retl 151; 152; X64-LABEL: TestFPTruncF128_F32: 153; X64: movaps vf128(%rip), %xmm0 154; X64-NEXT: callq __trunctfsf2 155; X64-NEXT: movss %xmm0, vf32(%rip) 156; X64: retq 157} 158 159define void @TestFPTruncF128_F64() { 160entry: 161 %0 = load fp128, fp128* @vf128, align 16 162 %conv = fptrunc fp128 %0 to double 163 store double %conv, double* @vf64, align 8 164 ret void 165; X32-LABEL: TestFPTruncF128_F64: 166; X32: calll __trunctfdf2 167; X32: fstpl vf64 168; X32: retl 169; 170; X64-LABEL: TestFPTruncF128_F64: 171; X64: movaps vf128(%rip), %xmm0 172; X64-NEXT: callq __trunctfdf2 173; X64-NEXT: movsd %xmm0, vf64(%rip) 174; X64: retq 175} 176 177define void @TestFPTruncF128_F80() { 178entry: 179 %0 = load fp128, fp128* @vf128, align 16 180 %conv = fptrunc fp128 %0 to x86_fp80 181 store x86_fp80 %conv, x86_fp80* @vf80, align 8 182 ret void 183; X32-LABEL: TestFPTruncF128_F80: 184; X32: calll __trunctfxf2 185; 186; X64-LABEL: TestFPTruncF128_F80: 187; X64: callq __trunctfxf2 188} 189 190define void @TestSIToFPI32_F128() { 191entry: 192 %0 = load i32, i32* @vi32, align 4 193 %conv = sitofp i32 %0 to fp128 194 store fp128 %conv, fp128* @vf128, align 16 195 ret void 196; X32-LABEL: TestSIToFPI32_F128: 197; X32: calll __floatsitf 198; X32: retl 199; 200; X64-LABEL: TestSIToFPI32_F128: 201; X64: movl vi32(%rip), %edi 202; X64-NEXT: callq __floatsitf 203; X64-NEXT: movaps %xmm0, vf128(%rip) 204; X64: retq 205} 206 207define void @TestUIToFPU32_F128() #2 { 208entry: 209 %0 = load i32, i32* @vu32, align 4 210 %conv = uitofp i32 %0 to fp128 211 store fp128 %conv, fp128* @vf128, align 16 212 ret void 213; X32-LABEL: TestUIToFPU32_F128: 214; X32: calll __floatunsitf 215; X32: retl 216; 217; X64-LABEL: TestUIToFPU32_F128: 218; X64: movl vu32(%rip), %edi 219; X64-NEXT: callq __floatunsitf 220; X64-NEXT: movaps %xmm0, vf128(%rip) 221; X64: retq 222} 223 224define void @TestSIToFPI64_F128(){ 225entry: 226 %0 = load i64, i64* @vi64, align 8 227 %conv = sitofp i64 %0 to fp128 228 store fp128 %conv, fp128* @vf128, align 16 229 ret void 230; X32-LABEL: TestSIToFPI64_F128: 231; X32: calll __floatditf 232; X32: retl 233; 234; X64-LABEL: TestSIToFPI64_F128: 235; X64: movq vi64(%rip), %rdi 236; X64-NEXT: callq __floatditf 237; X64-NEXT: movaps %xmm0, vf128(%rip) 238; X64: retq 239} 240 241define void @TestUIToFPU64_F128() #2 { 242entry: 243 %0 = load i64, i64* @vu64, align 8 244 %conv = uitofp i64 %0 to fp128 245 store fp128 %conv, fp128* @vf128, align 16 246 ret void 247; X32-LABEL: TestUIToFPU64_F128: 248; X32: calll __floatunditf 249; X32: retl 250; 251; X64-LABEL: TestUIToFPU64_F128: 252; X64: movq vu64(%rip), %rdi 253; X64-NEXT: callq __floatunditf 254; X64-NEXT: movaps %xmm0, vf128(%rip) 255; X64: retq 256} 257 258define i32 @TestConst128(fp128 %v) { 259entry: 260 %cmp = fcmp ogt fp128 %v, 0xL00000000000000003FFF000000000000 261 %conv = zext i1 %cmp to i32 262 ret i32 %conv 263; X32-LABEL: TestConst128: 264; X32: calll __gttf2 265; X32: retl 266; 267; X64-LABEL: TestConst128: 268; X64: movaps {{.*}}, %xmm1 269; X64-NEXT: callq __gttf2 270; X64-NEXT: xorl 271; X64-NEXT: test 272; X64: retq 273} 274 275; C code: 276; struct TestBits_ieee_ext { 277; unsigned v1; 278; unsigned v2; 279; }; 280; union TestBits_LDU { 281; FP128 ld; 282; struct TestBits_ieee_ext bits; 283; }; 284; int TestBits128(FP128 ld) { 285; union TestBits_LDU u; 286; u.ld = ld * ld; 287; return ((u.bits.v1 | u.bits.v2) == 0); 288; } 289define i32 @TestBits128(fp128 %ld) { 290entry: 291 %mul = fmul fp128 %ld, %ld 292 %0 = bitcast fp128 %mul to i128 293 %shift = lshr i128 %0, 32 294 %or5 = or i128 %shift, %0 295 %or = trunc i128 %or5 to i32 296 %cmp = icmp eq i32 %or, 0 297 %conv = zext i1 %cmp to i32 298 ret i32 %conv 299; X32-LABEL: TestBits128: 300; X32: calll __multf3 301; X32: retl 302; 303; X64-LABEL: TestBits128: 304; X64: movaps %xmm0, %xmm1 305; X64-NEXT: callq __multf3 306; X64-NEXT: movaps %xmm0, (%rsp) 307; X64-NEXT: movq (%rsp), 308; X64-NEXT: movq % 309; X64-NEXT: shrq $32, 310; X64: xorl %eax, %eax 311; X64-NEXT: orl 312; X64-NEXT: sete %al 313; X64: retq 314; 315; If TestBits128 fails due to any llvm or clang change, 316; please make sure the original simplified C code will 317; be compiled into correct IL and assembly code, not 318; just this TestBits128 test case. Better yet, try to 319; test the whole libm and its test cases. 320} 321 322; C code: (compiled with -target x86_64-linux-android) 323; typedef long double __float128; 324; __float128 TestPair128(unsigned long a, unsigned long b) { 325; unsigned __int128 n; 326; unsigned __int128 v1 = ((unsigned __int128)a << 64); 327; unsigned __int128 v2 = (unsigned __int128)b; 328; n = (v1 | v2) + 3; 329; return *(__float128*)&n; 330; } 331define fp128 @TestPair128(i64 %a, i64 %b) { 332entry: 333 %conv = zext i64 %a to i128 334 %shl = shl nuw i128 %conv, 64 335 %conv1 = zext i64 %b to i128 336 %or = or i128 %shl, %conv1 337 %add = add i128 %or, 3 338 %0 = bitcast i128 %add to fp128 339 ret fp128 %0 340; X32-LABEL: TestPair128: 341; X32: addl 342; X32-NEXT: adcl 343; X32-NEXT: adcl 344; X32-NEXT: adcl 345; X32: retl 346; 347; X64-LABEL: TestPair128: 348; X64: addq $3, %rsi 349; X64: movq %rsi, -24(%rsp) 350; X64: movq %rdi, -16(%rsp) 351; X64: movaps -24(%rsp), %xmm0 352; X64-NEXT: retq 353} 354 355define fp128 @TestTruncCopysign(fp128 %x, i32 %n) { 356entry: 357 %cmp = icmp sgt i32 %n, 50000 358 br i1 %cmp, label %if.then, label %cleanup 359 360if.then: ; preds = %entry 361 %conv = fptrunc fp128 %x to double 362 %call = tail call double @copysign(double 0x7FF0000000000000, double %conv) #2 363 %conv1 = fpext double %call to fp128 364 br label %cleanup 365 366cleanup: ; preds = %entry, %if.then 367 %retval.0 = phi fp128 [ %conv1, %if.then ], [ %x, %entry ] 368 ret fp128 %retval.0 369; X32-LABEL: TestTruncCopysign: 370; X32: calll __trunctfdf2 371; X32: fstpl 372; X32: flds 373; X32: flds 374; X32: fstp 375; X32: fldz 376; X32: fstp 377; X32: fstpl 378; X32: calll __extenddftf2 379; X32: retl 380; 381; X64-LABEL: TestTruncCopysign: 382; X64: callq __trunctfdf2 383; X64-NEXT: movsd {{.*}}, %xmm1 384; X64-NEXT: movlhps %xmm1, %xmm1 385; X64-NEXT: andps {{.*}}, %xmm0 386; X64-NEXT: orps %xmm1, %xmm0 387; X64-NEXT: callq __extenddftf2 388; X64: retq 389} 390 391define i1 @PR34866(i128 %x) { 392; X64-LABEL: PR34866: 393; X64: # %bb.0: 394; X64-NEXT: movaps {{.*}}(%rip), %xmm0 395; X64-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) 396; X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rsi 397; X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rdi 398; X64-NEXT: orq %rsi, %rdi 399; X64-NEXT: sete %al 400; X64-NEXT: retq 401; 402; X64_NO_MMX-LABEL: PR34866: 403; X64_NO_MMX: # %bb.0: 404; X64_NO_MMX-NEXT: orq %rsi, %rdi 405; X64_NO_MMX-NEXT: sete %al 406; X64_NO_MMX-NEXT: retq 407; 408; X32-LABEL: PR34866: 409; X32: # %bb.0: 410; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 411; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 412; X32-NEXT: orl {{[0-9]+}}(%esp), %ecx 413; X32-NEXT: orl {{[0-9]+}}(%esp), %eax 414; X32-NEXT: orl %ecx, %eax 415; X32-NEXT: sete %al 416; X32-NEXT: retl 417 %bc_mmx = bitcast fp128 0xL00000000000000000000000000000000 to i128 418 %cmp = icmp eq i128 %bc_mmx, %x 419 ret i1 %cmp 420} 421 422define i1 @PR34866_commute(i128 %x) { 423; X64-LABEL: PR34866_commute: 424; X64: # %bb.0: 425; X64-NEXT: movaps {{.*}}(%rip), %xmm0 426; X64-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) 427; X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rsi 428; X64-NEXT: xorq -{{[0-9]+}}(%rsp), %rdi 429; X64-NEXT: orq %rsi, %rdi 430; X64-NEXT: sete %al 431; X64-NEXT: retq 432; 433; X64_NO_MMX-LABEL: PR34866_commute: 434; X64_NO_MMX: # %bb.0: 435; X64_NO_MMX-NEXT: orq %rsi, %rdi 436; X64_NO_MMX-NEXT: sete %al 437; X64_NO_MMX-NEXT: retq 438; 439; X32-LABEL: PR34866_commute: 440; X32: # %bb.0: 441; X32-NEXT: movl {{[0-9]+}}(%esp), %eax 442; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx 443; X32-NEXT: orl {{[0-9]+}}(%esp), %ecx 444; X32-NEXT: orl {{[0-9]+}}(%esp), %eax 445; X32-NEXT: orl %ecx, %eax 446; X32-NEXT: sete %al 447; X32-NEXT: retl 448 %bc_mmx = bitcast fp128 0xL00000000000000000000000000000000 to i128 449 %cmp = icmp eq i128 %x, %bc_mmx 450 ret i1 %cmp 451} 452 453 454declare double @copysign(double, double) #1 455 456attributes #2 = { nounwind readnone } 457