1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -float2int -S | FileCheck %s 3; RUN: opt < %s -passes='float2int' -S | FileCheck %s 4 5; 6; Positive tests 7; 8 9define i16 @simple1(i8 %a) { 10; CHECK-LABEL: @simple1( 11; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 12; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1 13; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 14; CHECK-NEXT: ret i16 [[TMP2]] 15; 16 %t1 = uitofp i8 %a to float 17 %t2 = fadd float %t1, 1.0 18 %t3 = fptoui float %t2 to i16 19 ret i16 %t3 20} 21 22define i8 @simple2(i8 %a) { 23; CHECK-LABEL: @simple2( 24; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 25; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 26; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8 27; CHECK-NEXT: ret i8 [[TMP2]] 28; 29 %t1 = uitofp i8 %a to float 30 %t2 = fsub float %t1, 1.0 31 %t3 = fptoui float %t2 to i8 32 ret i8 %t3 33} 34 35define i32 @simple3(i8 %a) { 36; CHECK-LABEL: @simple3( 37; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 38; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 39; CHECK-NEXT: ret i32 [[T21]] 40; 41 %t1 = uitofp i8 %a to float 42 %t2 = fsub float %t1, 1.0 43 %t3 = fptoui float %t2 to i32 44 ret i32 %t3 45} 46 47define i1 @cmp(i8 %a, i8 %b) { 48; CHECK-LABEL: @cmp( 49; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 50; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 51; CHECK-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]] 52; CHECK-NEXT: ret i1 [[T31]] 53; 54 %t1 = uitofp i8 %a to float 55 %t2 = uitofp i8 %b to float 56 %t3 = fcmp ult float %t1, %t2 57 ret i1 %t3 58} 59 60define i32 @simple4(i32 %a) { 61; CHECK-LABEL: @simple4( 62; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[A:%.*]] to i64 63; CHECK-NEXT: [[T21:%.*]] = add i64 [[TMP1]], 1 64; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i32 65; CHECK-NEXT: ret i32 [[TMP2]] 66; 67 %t1 = uitofp i32 %a to double 68 %t2 = fadd double %t1, 1.0 69 %t3 = fptoui double %t2 to i32 70 ret i32 %t3 71} 72 73define i32 @simple5(i8 %a, i8 %b) { 74; CHECK-LABEL: @simple5( 75; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 76; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 77; CHECK-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 78; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] 79; CHECK-NEXT: ret i32 [[T42]] 80; 81 %t1 = uitofp i8 %a to float 82 %t2 = uitofp i8 %b to float 83 %t3 = fadd float %t1, 1.0 84 %t4 = fmul float %t3, %t2 85 %t5 = fptoui float %t4 to i32 86 ret i32 %t5 87} 88 89define i32 @simple6(i8 %a, i8 %b) { 90; CHECK-LABEL: @simple6( 91; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 92; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 93; CHECK-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] 94; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] 95; CHECK-NEXT: ret i32 [[T42]] 96; 97 %t1 = uitofp i8 %a to float 98 %t2 = uitofp i8 %b to float 99 %t3 = fneg float %t1 100 %t4 = fmul float %t3, %t2 101 %t5 = fptoui float %t4 to i32 102 ret i32 %t5 103} 104 105; The two chains don't interact - failure of one shouldn't 106; cause failure of the other. 107 108define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) { 109; CHECK-LABEL: @multi1( 110; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 111; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 112; CHECK-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float 113; CHECK-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]] 114; CHECK-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] 115; CHECK-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 116; CHECK-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]] 117; CHECK-NEXT: ret i32 [[R]] 118; 119 %fa = uitofp i8 %a to float 120 %fb = uitofp i8 %b to float 121 %fc = uitofp i8 %c to float 122 %x = fadd float %fa, %fb 123 %y = fptoui float %x to i32 124 %z = fadd float %fc, %d 125 %w = fptoui float %z to i32 126 %r = add i32 %y, %w 127 ret i32 %r 128} 129 130define i16 @simple_negzero(i8 %a) { 131; CHECK-LABEL: @simple_negzero( 132; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 133; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0 134; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 135; CHECK-NEXT: ret i16 [[TMP2]] 136; 137 %t1 = uitofp i8 %a to float 138 %t2 = fadd fast float %t1, -0.0 139 %t3 = fptoui float %t2 to i16 140 ret i16 %t3 141} 142 143define i32 @simple_negative(i8 %call) { 144; CHECK-LABEL: @simple_negative( 145; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32 146; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3 147; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8 148; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 149; CHECK-NEXT: ret i32 [[CONV3]] 150; 151 %conv1 = sitofp i8 %call to float 152 %mul = fmul float %conv1, -3.000000e+00 153 %conv2 = fptosi float %mul to i8 154 %conv3 = sext i8 %conv2 to i32 155 ret i32 %conv3 156} 157 158define i16 @simple_fneg(i8 %a) { 159; CHECK-LABEL: @simple_fneg( 160; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 161; CHECK-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]] 162; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 163; CHECK-NEXT: ret i16 [[TMP2]] 164; 165 %t1 = uitofp i8 %a to float 166 %t2 = fneg fast float %t1 167 %t3 = fptoui float %t2 to i16 168 ret i16 %t3 169} 170 171; 172; Negative tests 173; 174 175; The two chains intersect, which means because one fails, no 176; transform can occur. 177 178define i32 @neg_multi1(i8 %a, i8 %b, i8 %c, float %d) { 179; CHECK-LABEL: @neg_multi1( 180; CHECK-NEXT: [[FA:%.*]] = uitofp i8 [[A:%.*]] to float 181; CHECK-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float 182; CHECK-NEXT: [[X:%.*]] = fadd float [[FA]], [[FC]] 183; CHECK-NEXT: [[Y:%.*]] = fptoui float [[X]] to i32 184; CHECK-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] 185; CHECK-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 186; CHECK-NEXT: [[R:%.*]] = add i32 [[Y]], [[W]] 187; CHECK-NEXT: ret i32 [[R]] 188; 189 %fa = uitofp i8 %a to float 190 %fc = uitofp i8 %c to float 191 %x = fadd float %fa, %fc 192 %y = fptoui float %x to i32 193 %z = fadd float %fc, %d 194 %w = fptoui float %z to i32 195 %r = add i32 %y, %w 196 ret i32 %r 197} 198 199; The i32 * i32 = i64, which has 64 bits, which is greater than the 52 bits 200; that can be exactly represented in a double. 201 202define i64 @neg_muld(i32 %a, i32 %b) { 203; CHECK-LABEL: @neg_muld( 204; CHECK-NEXT: [[FA:%.*]] = uitofp i32 [[A:%.*]] to double 205; CHECK-NEXT: [[FB:%.*]] = uitofp i32 [[B:%.*]] to double 206; CHECK-NEXT: [[MUL:%.*]] = fmul double [[FA]], [[FB]] 207; CHECK-NEXT: [[R:%.*]] = fptoui double [[MUL]] to i64 208; CHECK-NEXT: ret i64 [[R]] 209; 210 %fa = uitofp i32 %a to double 211 %fb = uitofp i32 %b to double 212 %mul = fmul double %fa, %fb 213 %r = fptoui double %mul to i64 214 ret i64 %r 215} 216 217; The i16 * i16 = i32, which can't be represented in a float, but can in a 218; double. This should fail, as the written code uses floats, not doubles so 219; the original result may be inaccurate. 220 221define i32 @neg_mulf(i16 %a, i16 %b) { 222; CHECK-LABEL: @neg_mulf( 223; CHECK-NEXT: [[FA:%.*]] = uitofp i16 [[A:%.*]] to float 224; CHECK-NEXT: [[FB:%.*]] = uitofp i16 [[B:%.*]] to float 225; CHECK-NEXT: [[MUL:%.*]] = fmul float [[FA]], [[FB]] 226; CHECK-NEXT: [[R:%.*]] = fptoui float [[MUL]] to i32 227; CHECK-NEXT: ret i32 [[R]] 228; 229 %fa = uitofp i16 %a to float 230 %fb = uitofp i16 %b to float 231 %mul = fmul float %fa, %fb 232 %r = fptoui float %mul to i32 233 ret i32 %r 234} 235 236; "false" doesn't have an icmp equivalent. 237 238define i1 @neg_cmp(i8 %a, i8 %b) { 239; CHECK-LABEL: @neg_cmp( 240; CHECK-NEXT: [[T1:%.*]] = uitofp i8 [[A:%.*]] to float 241; CHECK-NEXT: [[T2:%.*]] = uitofp i8 [[B:%.*]] to float 242; CHECK-NEXT: [[T3:%.*]] = fcmp false float [[T1]], [[T2]] 243; CHECK-NEXT: ret i1 [[T3]] 244; 245 %t1 = uitofp i8 %a to float 246 %t2 = uitofp i8 %b to float 247 %t3 = fcmp false float %t1, %t2 248 ret i1 %t3 249} 250 251; Division isn't a supported operator. 252 253define i16 @neg_div(i8 %a) { 254; CHECK-LABEL: @neg_div( 255; CHECK-NEXT: [[T1:%.*]] = uitofp i8 [[A:%.*]] to float 256; CHECK-NEXT: [[T2:%.*]] = fdiv float [[T1]], 1.000000e+00 257; CHECK-NEXT: [[T3:%.*]] = fptoui float [[T2]] to i16 258; CHECK-NEXT: ret i16 [[T3]] 259; 260 %t1 = uitofp i8 %a to float 261 %t2 = fdiv float %t1, 1.0 262 %t3 = fptoui float %t2 to i16 263 ret i16 %t3 264} 265 266; 1.2 is not an integer. 267 268define i16 @neg_remainder(i8 %a) { 269; CHECK-LABEL: @neg_remainder( 270; CHECK-NEXT: [[T1:%.*]] = uitofp i8 [[A:%.*]] to float 271; CHECK-NEXT: [[T2:%.*]] = fadd float [[T1]], 1.250000e+00 272; CHECK-NEXT: [[T3:%.*]] = fptoui float [[T2]] to i16 273; CHECK-NEXT: ret i16 [[T3]] 274; 275 %t1 = uitofp i8 %a to float 276 %t2 = fadd float %t1, 1.25 277 %t3 = fptoui float %t2 to i16 278 ret i16 %t3 279} 280 281; i80 > i64, which is the largest bitwidth handleable by default. 282 283define i80 @neg_toolarge(i80 %a) { 284; CHECK-LABEL: @neg_toolarge( 285; CHECK-NEXT: [[T1:%.*]] = uitofp i80 [[A:%.*]] to fp128 286; CHECK-NEXT: [[T2:%.*]] = fadd fp128 [[T1]], [[T1]] 287; CHECK-NEXT: [[T3:%.*]] = fptoui fp128 [[T2]] to i80 288; CHECK-NEXT: ret i80 [[T3]] 289; 290 %t1 = uitofp i80 %a to fp128 291 %t2 = fadd fp128 %t1, %t1 292 %t3 = fptoui fp128 %t2 to i80 293 ret i80 %t3 294} 295 296; The sequence %t1..%t3 cannot be converted because %t4 uses %t2. 297 298define i32 @neg_calluser(i32 %value) { 299; CHECK-LABEL: @neg_calluser( 300; CHECK-NEXT: [[T1:%.*]] = sitofp i32 [[VALUE:%.*]] to double 301; CHECK-NEXT: [[T2:%.*]] = fadd double [[T1]], 1.000000e+00 302; CHECK-NEXT: [[T3:%.*]] = fcmp olt double [[T2]], 0.000000e+00 303; CHECK-NEXT: [[T4:%.*]] = tail call double @g(double [[T2]]) 304; CHECK-NEXT: [[T5:%.*]] = fptosi double [[T4]] to i32 305; CHECK-NEXT: [[T6:%.*]] = zext i1 [[T3]] to i32 306; CHECK-NEXT: [[T7:%.*]] = add i32 [[T6]], [[T5]] 307; CHECK-NEXT: ret i32 [[T7]] 308; 309 %t1 = sitofp i32 %value to double 310 %t2 = fadd double %t1, 1.0 311 %t3 = fcmp olt double %t2, 0.000000e+00 312 %t4 = tail call double @g(double %t2) 313 %t5 = fptosi double %t4 to i32 314 %t6 = zext i1 %t3 to i32 315 %t7 = add i32 %t6, %t5 316 ret i32 %t7 317} 318 319declare double @g(double) 320 321define <4 x i16> @neg_vector(<4 x i8> %a) { 322; CHECK-LABEL: @neg_vector( 323; CHECK-NEXT: [[T1:%.*]] = uitofp <4 x i8> [[A:%.*]] to <4 x float> 324; CHECK-NEXT: [[T2:%.*]] = fptoui <4 x float> [[T1]] to <4 x i16> 325; CHECK-NEXT: ret <4 x i16> [[T2]] 326; 327 %t1 = uitofp <4 x i8> %a to <4 x float> 328 %t2 = fptoui <4 x float> %t1 to <4 x i16> 329 ret <4 x i16> %t2 330} 331 332; Don't crash while processing unreachable (non-standard) IR. 333 334define void @PR38502() { 335; CHECK-LABEL: @PR38502( 336; CHECK-NEXT: entry: 337; CHECK-NEXT: ret void 338; CHECK: bogusBB: 339; CHECK-NEXT: [[INC1:%.*]] = fadd double [[INC:%.*]], 1.000000e+00 340; CHECK-NEXT: [[INC]] = fadd double [[INC1]], 1.000000e+00 341; CHECK-NEXT: [[TOBOOL:%.*]] = fcmp une double [[INC]], 0.000000e+00 342; CHECK-NEXT: br label [[BOGUSBB:%.*]] 343; 344entry: 345 ret void 346 347bogusBB: ; preds = %bogusBB 348 %inc1 = fadd double %inc, 1.000000e+00 349 %inc = fadd double %inc1, 1.000000e+00 350 %tobool = fcmp une double %inc, 0.000000e+00 351 br label %bogusBB 352} 353