1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s 3 4define ptr @simplify_phi_common_value_op0(ptr %ptr, ptr %b) { 5; CHECK-LABEL: @simplify_phi_common_value_op0( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[PTR:%.*]], null 8; CHECK-NEXT: br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]] 9; CHECK: else: 10; CHECK-NEXT: [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4 11; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LB]], 1 12; CHECK-NEXT: store i32 [[ADD]], ptr [[B]], align 4 13; CHECK-NEXT: br label [[RETURN]] 14; CHECK: return: 15; CHECK-NEXT: ret ptr [[PTR]] 16; 17entry: 18 %isnull = icmp eq ptr %ptr, null 19 br i1 %isnull, label %return, label %else 20 21else: 22 %lb = load i32, ptr %b 23 %add = add nsw i32 %lb, 1 24 store i32 %add, ptr %b 25 br label %return 26 27return: 28 %r = phi ptr [ %ptr, %else ], [ null, %entry ] 29 ret ptr %r 30} 31 32define ptr @simplify_phi_common_value_op1(ptr %ptr, ptr %b) { 33; CHECK-LABEL: @simplify_phi_common_value_op1( 34; CHECK-NEXT: entry: 35; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[PTR:%.*]], null 36; CHECK-NEXT: br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]] 37; CHECK: else: 38; CHECK-NEXT: [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4 39; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LB]], 1 40; CHECK-NEXT: store i32 [[ADD]], ptr [[B]], align 4 41; CHECK-NEXT: br label [[RETURN]] 42; CHECK: return: 43; CHECK-NEXT: ret ptr [[PTR]] 44; 45entry: 46 %isnull = icmp eq ptr %ptr, null 47 br i1 %isnull, label %return, label %else 48 49else: 50 %lb = load i32, ptr %b 51 %add = add i32 %lb, 1 52 store i32 %add, ptr %b 53 br label %return 54 55return: 56 %r = phi ptr [ null, %entry], [ %ptr, %else ] 57 ret ptr %r 58} 59 60define i8 @simplify_phi_multiple_constants(i8 %x, ptr %b) { 61; CHECK-LABEL: @simplify_phi_multiple_constants( 62; CHECK-NEXT: entry: 63; CHECK-NEXT: [[IS0:%.*]] = icmp eq i8 [[X:%.*]], 0 64; CHECK-NEXT: br i1 [[IS0]], label [[RETURN:%.*]], label [[ELSE1:%.*]] 65; CHECK: else1: 66; CHECK-NEXT: [[IS42:%.*]] = icmp eq i8 [[X]], 42 67; CHECK-NEXT: br i1 [[IS42]], label [[RETURN]], label [[ELSE2:%.*]] 68; CHECK: else2: 69; CHECK-NEXT: [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4 70; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LB]], 1 71; CHECK-NEXT: store i32 [[ADD]], ptr [[B]], align 4 72; CHECK-NEXT: br label [[RETURN]] 73; CHECK: return: 74; CHECK-NEXT: ret i8 [[X]] 75; 76entry: 77 %is0 = icmp eq i8 %x, 0 78 br i1 %is0, label %return, label %else1 79 80else1: 81 %is42 = icmp eq i8 %x, 42 82 br i1 %is42, label %return, label %else2 83 84else2: 85 %lb = load i32, ptr %b 86 %add = add i32 %lb, 1 87 store i32 %add, ptr %b 88 br label %return 89 90return: 91 %r = phi i8 [ 0, %entry], [ %x, %else2 ], [ 42, %else1 ] 92 ret i8 %r 93} 94 95define ptr @simplify_phi_common_value_from_instruction(ptr %ptr_op, ptr %b, i32 %i) { 96; CHECK-LABEL: @simplify_phi_common_value_from_instruction( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[PTR_OP:%.*]], i32 [[I:%.*]] 99; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[PTR]], null 100; CHECK-NEXT: br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]] 101; CHECK: else: 102; CHECK-NEXT: [[LB:%.*]] = load i32, ptr [[B:%.*]], align 4 103; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LB]], 1 104; CHECK-NEXT: store i32 [[ADD]], ptr [[B]], align 4 105; CHECK-NEXT: br label [[RETURN]] 106; CHECK: return: 107; CHECK-NEXT: ret ptr [[PTR]] 108; 109entry: 110 %ptr = getelementptr i8, ptr %ptr_op, i32 %i 111 %isnull = icmp eq ptr %ptr, null 112 br i1 %isnull, label %return, label %else 113 114else: 115 %lb = load i32, ptr %b 116 %add = add nsw i32 %lb, 1 117 store i32 %add, ptr %b 118 br label %return 119 120return: 121 %r = phi ptr [ %ptr, %else ], [ null, %entry ] 122 ret ptr %r 123} 124 125; The sub has 'nsw', so it is not safe to propagate that value along 126; the bb2 edge because that would propagate poison to the return. 127; FIXME: In this particular case, it would be possible to perform the 128; transform if we drop nowrap flags from the sub. 129 130define i32 @PR43802(i32 %arg) { 131; CHECK-LABEL: @PR43802( 132; CHECK-NEXT: entry: 133; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[ARG:%.*]] 134; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG]], -2147483648 135; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]] 136; CHECK: bb2: 137; CHECK-NEXT: br label [[BB3]] 138; CHECK: bb3: 139; CHECK-NEXT: [[R:%.*]] = phi i32 [ -2147483648, [[BB2]] ], [ [[SUB]], [[ENTRY:%.*]] ] 140; CHECK-NEXT: ret i32 [[R]] 141; 142entry: 143 %sub = sub nsw i32 0, %arg 144 %cmp = icmp eq i32 %arg, -2147483648 145 br i1 %cmp, label %bb2, label %bb3 146 147bb2: 148 br label %bb3 149 150bb3: 151 %r = phi i32 [ -2147483648, %bb2 ], [ %sub, %entry ] 152 ret i32 %r 153} 154 155; Same as previous test case, but without nowrap flags. 156define i32 @PR43802_without_nowrap(i32 %arg) { 157; CHECK-LABEL: @PR43802_without_nowrap( 158; CHECK-NEXT: entry: 159; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 0, [[ARG:%.*]] 160; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG]], -2147483648 161; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]] 162; CHECK: bb2: 163; CHECK-NEXT: br label [[BB3]] 164; CHECK: bb3: 165; CHECK-NEXT: [[SUB:%.*]] = phi i32 [ -2147483648, [[BB2]] ], [ [[SUB1]], [[ENTRY:%.*]] ] 166; CHECK-NEXT: ret i32 [[SUB]] 167; 168entry: 169 %sub = sub i32 0, %arg 170 %cmp = icmp eq i32 %arg, -2147483648 171 br i1 %cmp, label %bb2, label %bb3 172 173bb2: 174 br label %bb3 175 176bb3: 177 %r = phi i32 [ -2147483648, %bb2 ], [ %sub, %entry ] 178 ret i32 %r 179} 180 181; Similar to the previous case, we know that %y is always poison on the 182; entry -> join1 edge, and thus always zero or poison on the join1 -> join2 183; edge. We need to make sure that we don't replace zero with "zero or poison". 184 185define i8 @pr50399(i8 %x) { 186; CHECK-LABEL: @pr50399( 187; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -100 188; CHECK-NEXT: [[Y:%.*]] = add nsw i8 [[X]], -100 189; CHECK-NEXT: br i1 [[CMP]], label [[JOIN1:%.*]], label [[ELSE:%.*]] 190; CHECK: else: 191; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[Y]], 0 192; CHECK-NEXT: br i1 [[CMP2]], label [[JOIN1]], label [[ELSE2:%.*]] 193; CHECK: join1: 194; CHECK-NEXT: br label [[JOIN2:%.*]] 195; CHECK: else2: 196; CHECK-NEXT: br label [[JOIN2]] 197; CHECK: join2: 198; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ 0, [[JOIN1]] ], [ [[Y]], [[ELSE2]] ] 199; CHECK-NEXT: ret i8 [[PHI]] 200; 201 %cmp = icmp slt i8 %x, -100 202 %y = add nsw i8 %x, -100 203 br i1 %cmp, label %join1, label %else 204 205else: ; preds = %cond.end9 206 %cmp2 = icmp eq i8 %y, 0 207 br i1 %cmp2, label %join1, label %else2 208 209join1: 210 br label %join2 211 212else2: ; preds = %bb 213 br label %join2 214 215join2: 216 %phi = phi i8 [ 0, %join1 ], [ %y, %else2 ] 217 ret i8 %phi 218} 219