1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -passes=newgvn -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} 120 121define double @fcmp_une_not_zero(double %x, double %y) { 122; CHECK-LABEL: define double @fcmp_une_not_zero( 123; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 124; CHECK-NEXT: entry: 125; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], 2.000000e+00 126; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] 127; CHECK: else: 128; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 129; CHECK-NEXT: br label [[RETURN]] 130; CHECK: return: 131; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] 132; CHECK-NEXT: ret double [[RETVAL]] 133; 134entry: 135 %cmp = fcmp une double %y, 2.0 136 br i1 %cmp, label %return, label %else 137 138else: 139 %div = fdiv double %x, %y 140 br label %return 141 142return: 143 %retval = phi double [ %div, %else ], [ %x, %entry ] 144 ret double %retval 145 146} 147 148; PR22376 - We can't propagate zero constants because -0.0 149; compares equal to 0.0. If %y is -0.0 in this test case, 150; we would produce the wrong sign on the infinity return value. 151define double @fcmp_oeq_zero(double %x, double %y) { 152; CHECK-LABEL: define double @fcmp_oeq_zero( 153; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 154; CHECK-NEXT: entry: 155; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00 156; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]] 157; CHECK: if: 158; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 159; CHECK-NEXT: br label [[RETURN]] 160; CHECK: return: 161; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ] 162; CHECK-NEXT: ret double [[RETVAL]] 163; 164entry: 165 %cmp = fcmp oeq double %y, 0.0 166 br i1 %cmp, label %if, label %return 167 168if: 169 %div = fdiv double %x, %y 170 br label %return 171 172return: 173 %retval = phi double [ %div, %if ], [ %x, %entry ] 174 ret double %retval 175 176} 177 178define double @fcmp_une_zero(double %x, double %y) { 179; CHECK-LABEL: define double @fcmp_une_zero( 180; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { 181; CHECK-NEXT: entry: 182; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], -0.000000e+00 183; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] 184; CHECK: else: 185; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] 186; CHECK-NEXT: br label [[RETURN]] 187; CHECK: return: 188; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] 189; CHECK-NEXT: ret double [[RETVAL]] 190; 191entry: 192 %cmp = fcmp une double %y, -0.0 193 br i1 %cmp, label %return, label %else 194 195else: 196 %div = fdiv double %x, %y 197 br label %return 198 199return: 200 %retval = phi double [ %div, %else ], [ %x, %entry ] 201 ret double %retval 202 203} 204 205; We also cannot propagate a value if it's not a constant. 206; This is because the value could be 0.0 or -0.0. 207 208define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) { 209; CHECK-LABEL: define double @fcmp_oeq_maybe_zero( 210; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { 211; CHECK-NEXT: entry: 212; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] 213; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], [[Z]] 214; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]] 215; CHECK: if: 216; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] 217; CHECK-NEXT: br label [[RETURN]] 218; CHECK: return: 219; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ] 220; CHECK-NEXT: ret double [[RETVAL]] 221; 222entry: 223 %z = fadd double %z1, %z2 224 %cmp = fcmp oeq double %y, %z 225 br i1 %cmp, label %if, label %return 226 227if: 228 %div = fdiv double %x, %z 229 br label %return 230 231return: 232 %retval = phi double [ %div, %if ], [ %x, %entry ] 233 ret double %retval 234 235} 236 237define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) { 238; CHECK-LABEL: define double @fcmp_une_maybe_zero( 239; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { 240; CHECK-NEXT: entry: 241; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] 242; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], [[Z]] 243; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] 244; CHECK: else: 245; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] 246; CHECK-NEXT: br label [[RETURN]] 247; CHECK: return: 248; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] 249; CHECK-NEXT: ret double [[RETVAL]] 250; 251entry: 252 %z = fadd double %z1, %z2 253 %cmp = fcmp une double %y, %z 254 br i1 %cmp, label %return, label %else 255 256else: 257 %div = fdiv double %x, %z 258 br label %return 259 260return: 261 %retval = phi double [ %div, %else ], [ %x, %entry ] 262 ret double %retval 263 264} 265