1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=ipsccp -S | FileCheck %s 3 4declare void @use(i1) 5 6; We can simplify the conditions in the true block, because the condition 7; allows us to replace all uses of %a in the block with a constant. 8define void @val_undef_eq() { 9; CHECK-LABEL: @val_undef_eq( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[A:%.*]] = add nuw nsw i32 undef, 0 12; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 [[A]], 10 13; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] 14; CHECK: true: 15; CHECK-NEXT: call void @use(i1 false) 16; CHECK-NEXT: call void @use(i1 true) 17; CHECK-NEXT: ret void 18; CHECK: false: 19; CHECK-NEXT: ret void 20; 21entry: 22 %a = add i32 undef, 0 23 %bc.1 = icmp eq i32 %a, 10 24 br i1 %bc.1, label %true, label %false 25 26true: 27 %f.1 = icmp ne i32 %a, 10 28 call void @use(i1 %f.1) 29 %f.2 = icmp eq i32 %a, 10 30 call void @use(i1 %f.2) 31 ret void 32 33false: 34 ret void 35} 36 37declare void @use.i32(i32) 38 39; It is not allowed to use the range information from the condition to remove 40; %a.127 = and ... in the true block, as %a could be undef. 41define void @val_undef_range() { 42; CHECK-LABEL: @val_undef_range( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[A:%.*]] = add nuw nsw i32 undef, 0 45; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[A]], 127 46; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] 47; CHECK: true: 48; CHECK-NEXT: call void @use(i1 false) 49; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127 50; CHECK-NEXT: call void @use.i32(i32 [[A_127]]) 51; CHECK-NEXT: ret void 52; CHECK: false: 53; CHECK-NEXT: ret void 54; 55entry: 56 %a = add i32 undef, 0 57 %bc.1 = icmp ult i32 %a, 127 58 br i1 %bc.1, label %true, label %false 59 60true: 61 %f.1 = icmp eq i32 %a, 128 62 call void @use(i1 %f.1) 63 64 %a.127 = and i32 %a, 127 65 call void @use.i32(i32 %a.127) 66 ret void 67 68false: 69 ret void 70} 71 72; All uses of %p can be replaced by a constant (10). 73define void @val_singlecrfromundef_range(i1 %cond) { 74; CHECK-LABEL: @val_singlecrfromundef_range( 75; CHECK-NEXT: entry: 76; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]] 77; CHECK: inc1: 78; CHECK-NEXT: br label [[IF:%.*]] 79; CHECK: inc2: 80; CHECK-NEXT: br label [[IF]] 81; CHECK: if: 82; CHECK-NEXT: br label [[TRUE:%.*]] 83; CHECK: true: 84; CHECK-NEXT: call void @use(i1 false) 85; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127 86; CHECK-NEXT: call void @use.i32(i32 [[P_127]]) 87; CHECK-NEXT: ret void 88; 89entry: 90 91 br i1 %cond, label %inc1, label %inc2 92 93inc1: 94 br label %if 95 96inc2: 97 br label %if 98 99if: 100 %p = phi i32 [ 10, %inc1 ], [ undef, %inc2 ] 101 %bc.1 = icmp ult i32 %p, 127 102 br i1 %bc.1, label %true, label %false 103 104true: 105 %f.1 = icmp eq i32 %p, 128 106 call void @use(i1 %f.1) 107 108 %p.127 = and i32 %p, 127 109 call void @use.i32(i32 %p.127) 110 ret void 111 112false: 113 ret void 114} 115 116 117; It is not allowed to use the information from the condition ([0, 128)) 118; to remove a.127.2 = and i32 %p, 127, as %p might be undef. 119define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) { 120; CHECK-LABEL: @val_undef_to_cr_to_overdef_range( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A:%.*]], 127 123; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]] 124; CHECK: inc1: 125; CHECK-NEXT: br label [[IF:%.*]] 126; CHECK: inc2: 127; CHECK-NEXT: br label [[IF]] 128; CHECK: if: 129; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_127]], [[INC1]] ], [ undef, [[INC2]] ] 130; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[P]], 100 131; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] 132; CHECK: true: 133; CHECK-NEXT: call void @use(i1 false) 134; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127 135; CHECK-NEXT: call void @use.i32(i32 [[P_127]]) 136; CHECK-NEXT: ret void 137; CHECK: false: 138; CHECK-NEXT: ret void 139; 140entry: 141 %a.127 = and i32 %a, 127 142 br i1 %cond, label %inc1, label %inc2 143 144inc1: 145 br label %if 146 147inc2: 148 br label %if 149 150if: 151 %p = phi i32 [ %a.127, %inc1 ], [ undef, %inc2 ] 152 %bc.1 = icmp ult i32 %p, 100 153 br i1 %bc.1, label %true, label %false 154 155true: 156 %f.1 = icmp eq i32 %p, 128 157 call void @use(i1 %f.1) 158 159 %p.127 = and i32 %p, 127 160 call void @use.i32(i32 %p.127) 161 ret void 162 163false: 164 ret void 165} 166 167; All uses of %p can be replaced by a constant (10), we are allowed to use it 168; as a bound too. 169define void @bound_singlecrfromundef(i32 %a, i1 %cond) { 170; CHECK-LABEL: @bound_singlecrfromundef( 171; CHECK-NEXT: entry: 172; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 173; CHECK: bb1: 174; CHECK-NEXT: br label [[PRED:%.*]] 175; CHECK: bb2: 176; CHECK-NEXT: br label [[PRED]] 177; CHECK: pred: 178; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A:%.*]], 10 179; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] 180; CHECK: true: 181; CHECK-NEXT: call void @use(i1 false) 182; CHECK-NEXT: call void @use(i1 true) 183; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127 184; CHECK-NEXT: call void @use.i32(i32 [[A_127]]) 185; CHECK-NEXT: ret void 186; CHECK: false: 187; CHECK-NEXT: ret void 188; 189entry: 190 br i1 %cond, label %bb1, label %bb2 191 192bb1: 193 br label %pred 194 195bb2: 196 br label %pred 197 198pred: 199 %p = phi i32 [ undef, %bb1 ], [ 10, %bb2 ] 200 %bc.1 = icmp ugt i32 %a, %p 201 br i1 %bc.1, label %true, label %false 202 203true: 204 %f.1 = icmp eq i32 %a, 5 205 call void @use(i1 %f.1) 206 207 %t.1 = icmp ne i32 %a, 5 208 call void @use(i1 %t.1) 209 210 %a.127 = and i32 %a, 127 211 call void @use.i32(i32 %a.127) 212 213 ret void 214 215false: 216 ret void 217} 218 219; It is not allowed to use the information from %p as a bound, because an 220; incoming value is undef. 221define void @bound_range_and_undef(i32 %a, i1 %cond) { 222; CHECK-LABEL: @bound_range_and_undef( 223; CHECK-NEXT: entry: 224; CHECK-NEXT: [[A_10:%.*]] = and i32 [[A:%.*]], 127 225; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 226; CHECK: bb1: 227; CHECK-NEXT: br label [[PRED:%.*]] 228; CHECK: bb2: 229; CHECK-NEXT: br label [[PRED]] 230; CHECK: pred: 231; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_10]], [[BB1]] ], [ undef, [[BB2]] ] 232; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A]], [[P]] 233; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] 234; CHECK: true: 235; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 300 236; CHECK-NEXT: call void @use(i1 [[F_1]]) 237; CHECK-NEXT: [[A_127_2:%.*]] = and i32 [[P]], 127 238; CHECK-NEXT: call void @use.i32(i32 [[A_127_2]]) 239; CHECK-NEXT: ret void 240; CHECK: false: 241; CHECK-NEXT: ret void 242; 243entry: 244 %a.10 = and i32 %a, 127 245 br i1 %cond, label %bb1, label %bb2 246 247bb1: 248 br label %pred 249 250bb2: 251 br label %pred 252 253pred: 254 %p = phi i32 [ %a.10, %bb1 ], [ undef, %bb2 ] 255 %bc.1 = icmp ugt i32 %a, %p 256 br i1 %bc.1, label %true, label %false 257 258true: 259 %f.1 = icmp eq i32 %a, 300 260 call void @use(i1 %f.1) 261 262 %a.127.2 = and i32 %p, 127 263 call void @use.i32(i32 %a.127.2) 264 265 ret void 266 267false: 268 ret void 269} 270