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