1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @use(i1) 5 6define void @checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8 %n) { 7; CHECK-LABEL: @checks_in_loops_removable( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 10; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]] 11; CHECK: pre.1: 12; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16 13; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IDX_EXT]] 14; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[PTR_N]], [[UPPER:%.*]] 15; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]] 16; CHECK: pre.2: 17; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i8 [[N]], 0 18; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]] 19; CHECK: trap: 20; CHECK-NEXT: ret void 21; CHECK: loop.header: 22; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 23; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 24; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]] 25; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]] 26; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]] 27; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]] 28; CHECK: loop.latch: 29; CHECK-NEXT: store i8 0, ptr [[PTR_IV]], align 4 30; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 31; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV_NEXT]], [[IDX_EXT]] 32; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]] 33; CHECK: exit: 34; CHECK-NEXT: ret void 35; 36entry: 37 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 38 br i1 %cmp.ptr.lower, label %trap, label %pre.1 39 40pre.1: 41 %idx.ext = zext i8 %n to i16 42 %ptr.n = getelementptr inbounds i8, ptr %ptr, i16 %idx.ext 43 %cmp.ptr.n.upper = icmp ult ptr %ptr.n, %upper 44 br i1 %cmp.ptr.n.upper, label %pre.2, label %trap 45 46pre.2: 47 %cmp.n.not.zero = icmp eq i8 %n, 0 48 br i1 %cmp.n.not.zero, label %exit, label %loop.header 49 50trap: 51 ret void 52 53loop.header: 54 %iv = phi i16 [ 0, %pre.2 ], [ %iv.next, %loop.latch ] 55 %ptr.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 56 %cmp.ptr.iv.lower = icmp ugt ptr %lower, %ptr.iv 57 %cmp.ptr.iv.upper = icmp ule ptr %upper, %ptr.iv 58 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper 59 br i1 %or, label %trap, label %loop.latch 60 61loop.latch: 62 store i8 0, ptr %ptr.iv, align 4 63 %iv.next = add nuw nsw i16 %iv, 1 64 %exitcond = icmp ne i16 %iv.next, %idx.ext 65 br i1 %exitcond, label %loop.header, label %exit 66 67exit: 68 ret void 69} 70 71define void @some_checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8 %n) { 72; CHECK-LABEL: @some_checks_in_loops_removable( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 75; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]] 76; CHECK: pre.1: 77; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16 78; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IDX_EXT]] 79; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[PTR_N]], [[UPPER:%.*]] 80; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]] 81; CHECK: pre.2: 82; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i8 [[N]], 0 83; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]] 84; CHECK: trap: 85; CHECK-NEXT: ret void 86; CHECK: loop.header: 87; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 88; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 89; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]] 90; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]] 91; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]] 92; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]] 93; CHECK: loop.body: 94; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i16 [[IV]], 1 95; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV_1]] 96; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV_1]] 97; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]] 98; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]] 99; CHECK: loop.latch: 100; CHECK-NEXT: store i8 0, ptr [[PTR_IV]], align 4 101; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 102; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV_NEXT]], [[IDX_EXT]] 103; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]] 104; CHECK: exit: 105; CHECK-NEXT: ret void 106; 107entry: 108 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 109 br i1 %cmp.ptr.lower, label %trap, label %pre.1 110 111pre.1: 112 %idx.ext = zext i8 %n to i16 113 %ptr.n = getelementptr inbounds i8, ptr %ptr, i16 %idx.ext 114 %cmp.ptr.n.upper = icmp ult ptr %ptr.n, %upper 115 br i1 %cmp.ptr.n.upper, label %pre.2, label %trap 116 117pre.2: 118 %cmp.n.not.zero = icmp eq i8 %n, 0 119 br i1 %cmp.n.not.zero, label %exit, label %loop.header 120 121trap: 122 ret void 123 124loop.header: 125 %iv = phi i16 [ 0, %pre.2 ], [ %iv.next, %loop.latch ] 126 %ptr.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 127 %cmp.ptr.iv.lower = icmp ugt ptr %lower, %ptr.iv 128 %cmp.ptr.iv.upper = icmp ule ptr %upper, %ptr.iv 129 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper 130 br i1 %or, label %trap, label %loop.body 131 132loop.body: 133 %iv.1 = add nuw nsw i16 %iv, 1 134 %ptr.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %iv.1 135 %cmp.ptr.iv.1.lower = icmp ugt ptr %lower, %ptr.iv.1 136 %cmp.ptr.iv.1.upper = icmp ule ptr %upper, %ptr.iv.1 137 %or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper 138 br i1 %or, label %trap, label %loop.latch 139 140loop.latch: 141 store i8 0, ptr %ptr.iv, align 4 142 %iv.next = add nuw nsw i16 %iv, 1 143 %exitcond = icmp ne i16 %iv.next, %idx.ext 144 br i1 %exitcond, label %loop.header, label %exit 145 146exit: 147 ret void 148} 149 150; N might be zero, cannot remove upper checks. 151define void @no_checks_in_loops_removable(ptr %ptr, ptr %lower, ptr %upper, i8 %n) { 152; CHECK-LABEL: @no_checks_in_loops_removable( 153; CHECK-NEXT: entry: 154; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult ptr [[PTR:%.*]], [[LOWER:%.*]] 155; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]] 156; CHECK: pre.1: 157; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16 158; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IDX_EXT]] 159; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult ptr [[PTR_N]], [[UPPER:%.*]] 160; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[LOOP_HEADER:%.*]], label [[TRAP]] 161; CHECK: trap: 162; CHECK-NEXT: ret void 163; CHECK: loop.header: 164; CHECK-NEXT: [[IV:%.*]] = phi i16 [ 0, [[PRE_1]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 165; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV]] 166; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt ptr [[LOWER]], [[PTR_IV]] 167; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV]] 168; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[CMP_PTR_IV_UPPER]] 169; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]] 170; CHECK: loop.body: 171; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i16 [[IV]], 1 172; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i16 [[IV_1]] 173; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule ptr [[UPPER]], [[PTR_IV_1]] 174; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]] 175; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]] 176; CHECK: loop.latch: 177; CHECK-NEXT: store i8 0, ptr [[PTR_IV]], align 4 178; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1 179; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[IV_NEXT]], [[IDX_EXT]] 180; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 181; CHECK: exit: 182; CHECK-NEXT: ret void 183; 184entry: 185 %cmp.ptr.lower = icmp ult ptr %ptr, %lower 186 br i1 %cmp.ptr.lower, label %trap, label %pre.1 187 188pre.1: 189 %idx.ext = zext i8 %n to i16 190 %ptr.n = getelementptr inbounds i8, ptr %ptr, i16 %idx.ext 191 %cmp.ptr.n.upper = icmp ult ptr %ptr.n, %upper 192 br i1 %cmp.ptr.n.upper, label %loop.header, label %trap 193 194trap: 195 ret void 196 197loop.header: 198 %iv = phi i16 [ 0, %pre.1 ], [ %iv.next, %loop.latch ] 199 %ptr.iv = getelementptr inbounds i8, ptr %ptr, i16 %iv 200 %cmp.ptr.iv.lower = icmp ugt ptr %lower, %ptr.iv 201 %cmp.ptr.iv.upper = icmp ule ptr %upper, %ptr.iv 202 %or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper 203 br i1 %or, label %trap, label %loop.body 204 205loop.body: 206 %iv.1 = add nuw nsw i16 %iv, 1 207 %ptr.iv.1 = getelementptr inbounds i8, ptr %ptr, i16 %iv.1 208 %cmp.ptr.iv.1.lower = icmp ugt ptr %lower, %ptr.iv.1 209 %cmp.ptr.iv.1.upper = icmp ule ptr %upper, %ptr.iv.1 210 %or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper 211 br i1 %or, label %trap, label %loop.latch 212 213loop.latch: 214 store i8 0, ptr %ptr.iv, align 4 215 %iv.next = add nuw nsw i16 %iv, 1 216 %exitcond = icmp ne i16 %iv.next, %idx.ext 217 br i1 %exitcond, label %loop.header, label %exit 218 219exit: 220 ret void 221} 222