1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -passes=gvn -S < %s | FileCheck %s 3 4define i32 @f1(i32 %x) { 5; CHECK-LABEL: define i32 @f1( 6; CHECK-SAME: i32 [[X:%.*]]) { 7; CHECK-NEXT: [[BB0:.*:]] 8; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0 9; CHECK-NEXT: br i1 [[CMP]], label %[[BB2:.*]], label %[[BB1:.*]] 10; CHECK: [[BB1]]: 11; CHECK-NEXT: br label %[[BB2]] 12; CHECK: [[BB2]]: 13; CHECK-NEXT: ret i32 [[X]] 14; 15bb0: 16 %cmp = icmp eq i32 %x, 0 17 br i1 %cmp, label %bb2, label %bb1 18bb1: 19 br label %bb2 20bb2: 21 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] 22 %foo = add i32 %cond, %x 23 ret i32 %foo 24} 25 26define i32 @f2(i32 %x) { 27; CHECK-LABEL: define i32 @f2( 28; CHECK-SAME: i32 [[X:%.*]]) { 29; CHECK-NEXT: [[BB0:.*:]] 30; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X]], 0 31; CHECK-NEXT: br i1 [[CMP]], label %[[BB1:.*]], label %[[BB2:.*]] 32; CHECK: [[BB1]]: 33; CHECK-NEXT: br label %[[BB2]] 34; CHECK: [[BB2]]: 35; CHECK-NEXT: ret i32 [[X]] 36; 37bb0: 38 %cmp = icmp ne i32 %x, 0 39 br i1 %cmp, label %bb1, label %bb2 40bb1: 41 br label %bb2 42bb2: 43 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] 44 %foo = add i32 %cond, %x 45 ret i32 %foo 46} 47 48define i32 @f3(i32 %x) { 49; CHECK-LABEL: define i32 @f3( 50; CHECK-SAME: i32 [[X:%.*]]) { 51; CHECK-NEXT: [[BB0:.*:]] 52; CHECK-NEXT: switch i32 [[X]], label %[[BB1:.*]] [ 53; CHECK-NEXT: i32 0, label %[[BB2:.*]] 54; CHECK-NEXT: ] 55; CHECK: [[BB1]]: 56; CHECK-NEXT: br label %[[BB2]] 57; CHECK: [[BB2]]: 58; CHECK-NEXT: ret i32 [[X]] 59; 60bb0: 61 switch i32 %x, label %bb1 [ i32 0, label %bb2] 62bb1: 63 br label %bb2 64bb2: 65 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] 66 %foo = add i32 %cond, %x 67 ret i32 %foo 68} 69 70declare void @g(i1) 71define void @f4(ptr %x) { 72; CHECK-LABEL: define void @f4( 73; CHECK-SAME: ptr [[X:%.*]]) { 74; CHECK-NEXT: [[BB0:.*:]] 75; CHECK-NEXT: [[Y:%.*]] = icmp eq ptr null, [[X]] 76; CHECK-NEXT: br i1 [[Y]], label %[[BB2:.*]], label %[[BB1:.*]] 77; CHECK: [[BB1]]: 78; CHECK-NEXT: br label %[[BB2]] 79; CHECK: [[BB2]]: 80; CHECK-NEXT: call void @g(i1 [[Y]]) 81; CHECK-NEXT: ret void 82; 83bb0: 84 %y = icmp eq ptr null, %x 85 br i1 %y, label %bb2, label %bb1 86bb1: 87 br label %bb2 88bb2: 89 %zed = icmp eq ptr null, %x 90 call void @g(i1 %zed) 91 ret void 92} 93 94define double @fcmp_oeq_not_zero(double %x, double %y) { 95; CHECK-LABEL: define double @fcmp_oeq_not_zero( 96; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 97; CHECK-NEXT: [[ENTRY:.*]]: 98; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], 2.000000e+00 99; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]] 100; CHECK: [[IF]]: 101; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 102; CHECK-NEXT: br label %[[RETURN]] 103; CHECK: [[RETURN]]: 104; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ] 105; CHECK-NEXT: ret double [[RETVAL]] 106; 107entry: 108 %cmp = fcmp oeq double %y, 2.0 109 br i1 %cmp, label %if, label %return 110 111if: 112 %div = fdiv double %x, %y 113 br label %return 114 115return: 116 %retval = phi double [ %div, %if ], [ %x, %entry ] 117 ret double %retval 118} 119 120define double @fcmp_une_not_zero(double %x, double %y) { 121; CHECK-LABEL: define double @fcmp_une_not_zero( 122; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 123; CHECK-NEXT: [[ENTRY:.*]]: 124; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], 2.000000e+00 125; CHECK-NEXT: br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]] 126; CHECK: [[ELSE]]: 127; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 128; CHECK-NEXT: br label %[[RETURN]] 129; CHECK: [[RETURN]]: 130; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ] 131; CHECK-NEXT: ret double [[RETVAL]] 132; 133entry: 134 %cmp = fcmp une double %y, 2.0 135 br i1 %cmp, label %return, label %else 136 137else: 138 %div = fdiv double %x, %y 139 br label %return 140 141return: 142 %retval = phi double [ %div, %else ], [ %x, %entry ] 143 ret double %retval 144} 145 146define double @fcmp_one_possibly_nan(double %x, double %y) { 147; CHECK-LABEL: define double @fcmp_one_possibly_nan( 148; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 149; CHECK-NEXT: [[ENTRY:.*]]: 150; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[Y]], 2.000000e+00 151; CHECK-NEXT: br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]] 152; CHECK: [[ELSE]]: 153; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 154; CHECK-NEXT: br label %[[RETURN]] 155; CHECK: [[RETURN]]: 156; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ] 157; CHECK-NEXT: ret double [[RETVAL]] 158; 159entry: 160 %cmp = fcmp one double %y, 2.0 161 br i1 %cmp, label %return, label %else 162 163else: 164 %div = fdiv double %x, %y 165 br label %return 166 167return: 168 %retval = phi double [ %div, %else ], [ %x, %entry ] 169 ret double %retval 170} 171 172define double @fcmp_one_not_zero_or_nan(double %x, double %y) { 173; CHECK-LABEL: define double @fcmp_one_not_zero_or_nan( 174; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 175; CHECK-NEXT: [[ENTRY:.*]]: 176; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one double [[Y]], 2.000000e+00 177; CHECK-NEXT: br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]] 178; CHECK: [[ELSE]]: 179; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 180; CHECK-NEXT: br label %[[RETURN]] 181; CHECK: [[RETURN]]: 182; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ] 183; CHECK-NEXT: ret double [[RETVAL]] 184; 185entry: 186 %cmp = fcmp nnan one double %y, 2.0 187 br i1 %cmp, label %return, label %else 188 189else: 190 %div = fdiv double %x, %y 191 br label %return 192 193return: 194 %retval = phi double [ %div, %else ], [ %x, %entry ] 195 ret double %retval 196} 197 198; PR22376 - We can't propagate zero constants because -0.0 199; compares equal to 0.0. If %y is -0.0 in this test case, 200; we would produce the wrong sign on the infinity return value. 201define double @fcmp_oeq_zero(double %x, double %y) { 202; CHECK-LABEL: define double @fcmp_oeq_zero( 203; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 204; CHECK-NEXT: [[ENTRY:.*]]: 205; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00 206; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]] 207; CHECK: [[IF]]: 208; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 209; CHECK-NEXT: br label %[[RETURN]] 210; CHECK: [[RETURN]]: 211; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ] 212; CHECK-NEXT: ret double [[RETVAL]] 213; 214entry: 215 %cmp = fcmp oeq double %y, 0.0 216 br i1 %cmp, label %if, label %return 217 218if: 219 %div = fdiv double %x, %y 220 br label %return 221 222return: 223 %retval = phi double [ %div, %if ], [ %x, %entry ] 224 ret double %retval 225} 226 227; Denormals may be flushed to zero in some cases by the backend. 228; Hence, treat denormals as 0. 229define float @fcmp_oeq_denormal(float %x, float %y) { 230; CHECK-LABEL: define float @fcmp_oeq_denormal( 231; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { 232; CHECK-NEXT: [[ENTRY:.*]]: 233; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[Y]], 0x3800000000000000 234; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]] 235; CHECK: [[IF]]: 236; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X]], [[Y]] 237; CHECK-NEXT: br label %[[RETURN]] 238; CHECK: [[RETURN]]: 239; CHECK-NEXT: [[RETVAL:%.*]] = phi float [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ] 240; CHECK-NEXT: ret float [[RETVAL]] 241; 242entry: 243 %cmp = fcmp oeq float %y, 0x3800000000000000 244 br i1 %cmp, label %if, label %return 245 246if: 247 %div = fdiv float %x, %y 248 br label %return 249 250return: 251 %retval = phi float [ %div, %if ], [ %x, %entry ] 252 ret float %retval 253} 254 255define double @fcmp_une_zero(double %x, double %y) { 256; CHECK-LABEL: define double @fcmp_une_zero( 257; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 258; CHECK-NEXT: [[ENTRY:.*]]: 259; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], -0.000000e+00 260; CHECK-NEXT: br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]] 261; CHECK: [[ELSE]]: 262; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 263; CHECK-NEXT: br label %[[RETURN]] 264; CHECK: [[RETURN]]: 265; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ] 266; CHECK-NEXT: ret double [[RETVAL]] 267; 268entry: 269 %cmp = fcmp une double %y, -0.0 270 br i1 %cmp, label %return, label %else 271 272else: 273 %div = fdiv double %x, %y 274 br label %return 275 276return: 277 %retval = phi double [ %div, %else ], [ %x, %entry ] 278 ret double %retval 279} 280 281; We also cannot propagate a value if it's not a constant. 282; This is because the value could be 0.0, -0.0, or a denormal. 283 284define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) { 285; CHECK-LABEL: define double @fcmp_oeq_maybe_zero( 286; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { 287; CHECK-NEXT: [[ENTRY:.*]]: 288; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] 289; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], [[Z]] 290; CHECK-NEXT: br i1 [[CMP]], label %[[IF:.*]], label %[[RETURN:.*]] 291; CHECK: [[IF]]: 292; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] 293; CHECK-NEXT: br label %[[RETURN]] 294; CHECK: [[RETURN]]: 295; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[IF]] ], [ [[X]], %[[ENTRY]] ] 296; CHECK-NEXT: ret double [[RETVAL]] 297; 298entry: 299 %z = fadd double %z1, %z2 300 %cmp = fcmp oeq double %y, %z 301 br i1 %cmp, label %if, label %return 302 303if: 304 %div = fdiv double %x, %z 305 br label %return 306 307return: 308 %retval = phi double [ %div, %if ], [ %x, %entry ] 309 ret double %retval 310} 311 312define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) { 313; CHECK-LABEL: define double @fcmp_une_maybe_zero( 314; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { 315; CHECK-NEXT: [[ENTRY:.*]]: 316; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] 317; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], [[Z]] 318; CHECK-NEXT: br i1 [[CMP]], label %[[RETURN:.*]], label %[[ELSE:.*]] 319; CHECK: [[ELSE]]: 320; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] 321; CHECK-NEXT: br label %[[RETURN]] 322; CHECK: [[RETURN]]: 323; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[ELSE]] ], [ [[X]], %[[ENTRY]] ] 324; CHECK-NEXT: ret double [[RETVAL]] 325; 326entry: 327 %z = fadd double %z1, %z2 328 %cmp = fcmp une double %y, %z 329 br i1 %cmp, label %return, label %else 330 331else: 332 %div = fdiv double %x, %z 333 br label %return 334 335return: 336 %retval = phi double [ %div, %else ], [ %x, %entry ] 337 ret double %retval 338} 339 340 341define double @fcmp_ueq_possibly_nan(double %x, double %y) { 342; CHECK-LABEL: define double @fcmp_ueq_possibly_nan( 343; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 344; CHECK-NEXT: [[ENTRY:.*]]: 345; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[Y]], 2.000000e+00 346; CHECK-NEXT: br i1 [[CMP]], label %[[DO_DIV:.*]], label %[[RETURN:.*]] 347; CHECK: [[DO_DIV]]: 348; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 349; CHECK-NEXT: br label %[[RETURN]] 350; CHECK: [[RETURN]]: 351; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[DO_DIV]] ], [ [[X]], %[[ENTRY]] ] 352; CHECK-NEXT: ret double [[RETVAL]] 353; 354entry: 355 %cmp = fcmp ueq double %y, 2.0 356 br i1 %cmp, label %do_div, label %return 357 358do_div: 359 %div = fdiv double %x, %y 360 br label %return 361 362return: 363 %retval = phi double [ %div, %do_div ], [ %x, %entry ] 364 ret double %retval 365} 366 367define double @fcmp_ueq_not_zero_or_nan(double %x, double %y) { 368; CHECK-LABEL: define double @fcmp_ueq_not_zero_or_nan( 369; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 370; CHECK-NEXT: [[ENTRY:.*]]: 371; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ueq double [[Y]], 2.000000e+00 372; CHECK-NEXT: br i1 [[CMP]], label %[[DO_DIV:.*]], label %[[RETURN:.*]] 373; CHECK: [[DO_DIV]]: 374; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 375; CHECK-NEXT: br label %[[RETURN]] 376; CHECK: [[RETURN]]: 377; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], %[[DO_DIV]] ], [ [[X]], %[[ENTRY]] ] 378; CHECK-NEXT: ret double [[RETVAL]] 379; 380entry: 381 %cmp = fcmp nnan ueq double %y, 2.0 382 br i1 %cmp, label %do_div, label %return 383 384do_div: 385 %div = fdiv double %x, %y 386 br label %return 387 388return: 389 %retval = phi double [ %div, %do_div ], [ %x, %entry ] 390 ret double %retval 391} 392