1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4declare double @llvm.fabs.f64(double) readnone 5 6define i1 @test1(float %x, float %y) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] 9; CHECK-NEXT: ret i1 [[CMP]] 10; 11 %ext1 = fpext float %x to double 12 %ext2 = fpext float %y to double 13 %cmp = fcmp ogt double %ext1, %ext2 14 ret i1 %cmp 15} 16 17define i1 @test2(float %a) { 18; CHECK-LABEL: @test2( 19; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 1.000000e+00 20; CHECK-NEXT: ret i1 [[CMP]] 21; 22 %ext = fpext float %a to double 23 %cmp = fcmp ogt double %ext, 1.000000e+00 24 ret i1 %cmp 25} 26 27define i1 @test3(float %a) { 28; CHECK-LABEL: @test3( 29; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 30; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001 31; CHECK-NEXT: ret i1 [[CMP]] 32; 33 %ext = fpext float %a to double 34 %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float. 35 ret i1 %cmp 36} 37 38define i1 @test4(float %a) { 39; CHECK-LABEL: @test4( 40; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 41; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000 42; CHECK-NEXT: ret i1 [[CMP]] 43; 44 %ext = fpext float %a to double 45 %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float. 46 ret i1 %cmp 47} 48 49define i1 @fneg_constant_swap_pred(float %x) { 50; CHECK-LABEL: @fneg_constant_swap_pred( 51; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00 52; CHECK-NEXT: ret i1 [[CMP]] 53; 54 %neg = fsub float -0.0, %x 55 %cmp = fcmp ogt float %neg, 1.0 56 ret i1 %cmp 57} 58 59define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) { 60; CHECK-LABEL: @fneg_constant_swap_pred_vec( 61; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 62; CHECK-NEXT: ret <2 x i1> [[CMP]] 63; 64 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 65 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 66 ret <2 x i1> %cmp 67} 68 69define <2 x i1> @fneg_constant_swap_pred_vec_undef(<2 x float> %x) { 70; CHECK-LABEL: @fneg_constant_swap_pred_vec_undef( 71; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 72; CHECK-NEXT: ret <2 x i1> [[CMP]] 73; 74 %neg = fsub <2 x float> <float undef, float -0.0>, %x 75 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 76 ret <2 x i1> %cmp 77} 78 79define i1 @fneg_fneg_swap_pred(float %x, float %y) { 80; CHECK-LABEL: @fneg_fneg_swap_pred( 81; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] 82; CHECK-NEXT: ret i1 [[CMP]] 83; 84 %neg1 = fsub float -0.0, %x 85 %neg2 = fsub float -0.0, %y 86 %cmp = fcmp olt float %neg1, %neg2 87 ret i1 %cmp 88} 89 90define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 91; CHECK-LABEL: @fneg_fneg_swap_pred_vec( 92; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 93; CHECK-NEXT: ret <2 x i1> [[CMP]] 94; 95 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x 96 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y 97 %cmp = fcmp olt <2 x float> %neg1, %neg2 98 ret <2 x i1> %cmp 99} 100 101define <2 x i1> @fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { 102; CHECK-LABEL: @fneg_fneg_swap_pred_vec_undef( 103; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 104; CHECK-NEXT: ret <2 x i1> [[CMP]] 105; 106 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x 107 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y 108 %cmp = fcmp olt <2 x float> %neg1, %neg2 109 ret <2 x i1> %cmp 110} 111 112define i1 @test7(float %x) { 113; CHECK-LABEL: @test7( 114; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00 115; CHECK-NEXT: ret i1 [[CMP]] 116; 117 %ext = fpext float %x to ppc_fp128 118 %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000 119 ret i1 %cmp 120} 121 122define float @test8(float %x) { 123; CHECK-LABEL: @test8( 124; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 125; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float 126; CHECK-NEXT: ret float [[CONV2]] 127; 128 %conv = fpext float %x to double 129 %cmp = fcmp olt double %conv, 0.000000e+00 130 %conv1 = zext i1 %cmp to i32 131 %conv2 = sitofp i32 %conv1 to float 132 ret float %conv2 133; Float comparison to zero shouldn't cast to double. 134} 135 136declare double @fabs(double) readnone 137 138define i32 @test9(double %a) { 139; CHECK-LABEL: @test9( 140; CHECK-NEXT: ret i32 0 141; 142 %call = tail call double @fabs(double %a) 143 %cmp = fcmp olt double %call, 0.000000e+00 144 %conv = zext i1 %cmp to i32 145 ret i32 %conv 146} 147 148define i32 @test9_intrinsic(double %a) { 149; CHECK-LABEL: @test9_intrinsic( 150; CHECK-NEXT: ret i32 0 151; 152 %call = tail call double @llvm.fabs.f64(double %a) 153 %cmp = fcmp olt double %call, 0.000000e+00 154 %conv = zext i1 %cmp to i32 155 ret i32 %conv 156} 157 158define i32 @test10(double %a) { 159; CHECK-LABEL: @test10( 160; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 161; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 162; CHECK-NEXT: ret i32 [[CONV]] 163; 164 %call = tail call double @fabs(double %a) 165 %cmp = fcmp ole double %call, 0.000000e+00 166 %conv = zext i1 %cmp to i32 167 ret i32 %conv 168} 169 170define i32 @test10_intrinsic(double %a) { 171; CHECK-LABEL: @test10_intrinsic( 172; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 173; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 174; CHECK-NEXT: ret i32 [[CONV]] 175; 176 %call = tail call double @llvm.fabs.f64(double %a) 177 %cmp = fcmp ole double %call, 0.000000e+00 178 %conv = zext i1 %cmp to i32 179 ret i32 %conv 180} 181 182define i32 @test11(double %a) { 183; CHECK-LABEL: @test11( 184; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 185; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 186; CHECK-NEXT: ret i32 [[CONV]] 187; 188 %call = tail call double @fabs(double %a) 189 %cmp = fcmp ogt double %call, 0.000000e+00 190 %conv = zext i1 %cmp to i32 191 ret i32 %conv 192} 193 194define i32 @test11_intrinsic(double %a) { 195; CHECK-LABEL: @test11_intrinsic( 196; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 197; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 198; CHECK-NEXT: ret i32 [[CONV]] 199; 200 %call = tail call double @llvm.fabs.f64(double %a) 201 %cmp = fcmp ogt double %call, 0.000000e+00 202 %conv = zext i1 %cmp to i32 203 ret i32 %conv 204} 205 206define i32 @test12(double %a) { 207; CHECK-LABEL: @test12( 208; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 209; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 210; CHECK-NEXT: ret i32 [[CONV]] 211; 212 %call = tail call double @fabs(double %a) 213 %cmp = fcmp oge double %call, 0.000000e+00 214 %conv = zext i1 %cmp to i32 215 ret i32 %conv 216} 217 218define i32 @test12_intrinsic(double %a) { 219; CHECK-LABEL: @test12_intrinsic( 220; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 221; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 222; CHECK-NEXT: ret i32 [[CONV]] 223; 224 %call = tail call double @llvm.fabs.f64(double %a) 225 %cmp = fcmp oge double %call, 0.000000e+00 226 %conv = zext i1 %cmp to i32 227 ret i32 %conv 228} 229 230define i32 @test13(double %a) { 231; CHECK-LABEL: @test13( 232; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 233; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 234; CHECK-NEXT: ret i32 [[CONV]] 235; 236 %call = tail call double @fabs(double %a) 237 %cmp = fcmp une double %call, 0.000000e+00 238 %conv = zext i1 %cmp to i32 239 ret i32 %conv 240} 241 242define i32 @test13_intrinsic(double %a) { 243; CHECK-LABEL: @test13_intrinsic( 244; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 245; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 246; CHECK-NEXT: ret i32 [[CONV]] 247; 248 %call = tail call double @llvm.fabs.f64(double %a) 249 %cmp = fcmp une double %call, 0.000000e+00 250 %conv = zext i1 %cmp to i32 251 ret i32 %conv 252} 253 254define i32 @test14(double %a) { 255; CHECK-LABEL: @test14( 256; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 257; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 258; CHECK-NEXT: ret i32 [[CONV]] 259; 260 %call = tail call double @fabs(double %a) 261 %cmp = fcmp oeq double %call, 0.000000e+00 262 %conv = zext i1 %cmp to i32 263 ret i32 %conv 264} 265 266define i32 @test14_intrinsic(double %a) { 267; CHECK-LABEL: @test14_intrinsic( 268; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 269; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 270; CHECK-NEXT: ret i32 [[CONV]] 271; 272 %call = tail call double @llvm.fabs.f64(double %a) 273 %cmp = fcmp oeq double %call, 0.000000e+00 274 %conv = zext i1 %cmp to i32 275 ret i32 %conv 276} 277 278define i32 @test15(double %a) { 279; CHECK-LABEL: @test15( 280; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 281; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 282; CHECK-NEXT: ret i32 [[CONV]] 283; 284 %call = tail call double @fabs(double %a) 285 %cmp = fcmp one double %call, 0.000000e+00 286 %conv = zext i1 %cmp to i32 287 ret i32 %conv 288} 289 290define i32 @test15_intrinsic(double %a) { 291; CHECK-LABEL: @test15_intrinsic( 292; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 293; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 294; CHECK-NEXT: ret i32 [[CONV]] 295; 296 %call = tail call double @llvm.fabs.f64(double %a) 297 %cmp = fcmp one double %call, 0.000000e+00 298 %conv = zext i1 %cmp to i32 299 ret i32 %conv 300} 301 302define i32 @test16(double %a) { 303; CHECK-LABEL: @test16( 304; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 305; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 306; CHECK-NEXT: ret i32 [[CONV]] 307; 308 %call = tail call double @fabs(double %a) 309 %cmp = fcmp ueq double %call, 0.000000e+00 310 %conv = zext i1 %cmp to i32 311 ret i32 %conv 312} 313 314define i32 @test16_intrinsic(double %a) { 315; CHECK-LABEL: @test16_intrinsic( 316; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 317; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 318; CHECK-NEXT: ret i32 [[CONV]] 319; 320 %call = tail call double @llvm.fabs.f64(double %a) 321 %cmp = fcmp ueq double %call, 0.000000e+00 322 %conv = zext i1 %cmp to i32 323 ret i32 %conv 324} 325 326; Don't crash. 327define i32 @test17(double %a, double (double)* %p) { 328; CHECK-LABEL: @test17( 329; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]]) 330; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00 331; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 332; CHECK-NEXT: ret i32 [[CONV]] 333; 334 %call = tail call double %p(double %a) 335 %cmp = fcmp ueq double %call, 0.000000e+00 336 %conv = zext i1 %cmp to i32 337 ret i32 %conv 338} 339 340; Can fold fcmp with undef on one side by choosing NaN for the undef 341define i32 @test18_undef_unordered(float %a) { 342; CHECK-LABEL: @test18_undef_unordered( 343; CHECK-NEXT: ret i32 1 344; 345 %cmp = fcmp ueq float %a, undef 346 %conv = zext i1 %cmp to i32 347 ret i32 %conv 348} 349; Can fold fcmp with undef on one side by choosing NaN for the undef 350define i32 @test18_undef_ordered(float %a) { 351; CHECK-LABEL: @test18_undef_ordered( 352; CHECK-NEXT: ret i32 0 353; 354 %cmp = fcmp oeq float %a, undef 355 %conv = zext i1 %cmp to i32 356 ret i32 %conv 357} 358 359; Can fold fcmp with undef on both side 360; fcmp u_pred undef, undef -> true 361; fcmp o_pred undef, undef -> false 362; because whatever you choose for the first undef 363; you can choose NaN for the other undef 364define i1 @test19_undef_unordered() { 365; CHECK-LABEL: @test19_undef_unordered( 366; CHECK-NEXT: ret i1 true 367; 368 %cmp = fcmp ueq float undef, undef 369 ret i1 %cmp 370} 371 372define i1 @test19_undef_ordered() { 373; CHECK-LABEL: @test19_undef_ordered( 374; CHECK-NEXT: ret i1 false 375; 376 %cmp = fcmp oeq float undef, undef 377 ret i1 %cmp 378} 379 380