485 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 62; RUN: opt -passes='default<O2>' -S %s | FileCheck %s3 4; Slightly reduced test case for a loop iterating over a std::span with libc++ hardening.5; TODO: The runtime check in the loop should be removed.6;7; #include <span>8; #include <iostream>9;10; void use(unsigned&);11;12; void fill_with_foreach(std::span<unsigned> elems) {13; for (unsigned& x : elems)14; use(x);15; }16 17%"class.std::__1::span" = type { ptr, i64 }18%"struct.std::__1::__bounded_iter" = type { ptr, ptr, ptr }19 20define void @test_fill_with_foreach([2 x i64] %elems.coerce) {21; CHECK-LABEL: define void @test_fill_with_foreach(22; CHECK-SAME: [2 x i64] [[ELEMS_COERCE:%.*]]) local_unnamed_addr {23; CHECK-NEXT: [[ENTRY:.*:]]24; CHECK-NEXT: [[ELEMS_COERCE_FCA_0_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 025; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[ELEMS_COERCE_FCA_0_EXTRACT]] to ptr26; CHECK-NEXT: [[ELEMS_COERCE_FCA_1_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 127; CHECK-NEXT: [[ADD_PTR_I_IDX:%.*]] = shl nsw i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 228; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[ADD_PTR_I_IDX]]29; CHECK-NEXT: [[CMP_NOT_I_I_I_I:%.*]] = icmp slt i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 030; CHECK-NEXT: br i1 [[CMP_NOT_I_I_I_I]], label %[[ERROR:.*]], label %[[FOR_COND_PREHEADER_SPLIT:.*]]31; CHECK: [[FOR_COND_PREHEADER_SPLIT]]:32; CHECK-NEXT: [[CMP_I_NOT2:%.*]] = icmp eq i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 033; CHECK-NEXT: br i1 [[CMP_I_NOT2]], label %[[COMMON_RET:.*]], label %[[FOR_BODY:.*]]34; CHECK: [[COMMON_RET]]:35; CHECK-NEXT: ret void36; CHECK: [[ERROR]]:37; CHECK-NEXT: tail call void @error()38; CHECK-NEXT: br label %[[COMMON_RET]]39; CHECK: [[FOR_BODY]]:40; CHECK-NEXT: [[__BEGIN1_SROA_0_03:%.*]] = phi ptr [ [[INCDEC_PTR_I:%.*]], %[[FOR_BODY]] ], [ [[TMP0]], %[[FOR_COND_PREHEADER_SPLIT]] ]41; CHECK-NEXT: tail call void @use(ptr noundef nonnull align 4 dereferenceable(4) [[__BEGIN1_SROA_0_03]])42; CHECK-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__BEGIN1_SROA_0_03]], i64 443; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq ptr [[INCDEC_PTR_I]], [[ADD_PTR_I]]44; CHECK-NEXT: br i1 [[CMP_I_NOT]], label %[[COMMON_RET]], label %[[FOR_BODY]]45;46entry:47 %elems = alloca %"class.std::__1::span", align 848 %__begin1 = alloca %"struct.std::__1::__bounded_iter", align 849 %__end1 = alloca %"struct.std::__1::__bounded_iter", align 850 %elems.coerce.fca.0.extract = extractvalue [2 x i64] %elems.coerce, 051 store i64 %elems.coerce.fca.0.extract, ptr %elems, align 852 %elems.coerce.fca.1.extract = extractvalue [2 x i64] %elems.coerce, 153 %elems.coerce.fca.1.gep = getelementptr inbounds [2 x i64], ptr %elems, i64 0, i64 154 store i64 %elems.coerce.fca.1.extract, ptr %elems.coerce.fca.1.gep, align 855 call void @llvm.lifetime.start.p0(ptr nonnull %__begin1) #656 %0 = load ptr, ptr %elems, align 857 %__size_.i.i = getelementptr inbounds %"class.std::__1::span", ptr %elems, i64 0, i32 158 %1 = load i64, ptr %__size_.i.i, align 859 %add.ptr.i = getelementptr inbounds i32, ptr %0, i64 %160 store ptr %0, ptr %__begin1, align 861 %__begin_.i.i.i.i = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__begin1, i64 0, i32 162 store ptr %0, ptr %__begin_.i.i.i.i, align 863 %__end_.i.i.i.i = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__begin1, i64 0, i32 264 store ptr %add.ptr.i, ptr %__end_.i.i.i.i, align 865 %cmp.not.i.i.i.i = icmp slt i64 %1, 066 br i1 %cmp.not.i.i.i.i, label %error, label %check.267 68check.2:69 call void @llvm.lifetime.start.p0(ptr nonnull %__end1) #670 %l4 = load ptr, ptr %elems, align 871 %__size_.i.i4 = getelementptr inbounds %"class.std::__1::span", ptr %elems, i64 0, i32 172 %l5 = load i64, ptr %__size_.i.i4, align 873 %add.ptr.i5 = getelementptr inbounds i32, ptr %l4, i64 %l574 store ptr %add.ptr.i5, ptr %__end1, align 875 %__begin_.i.i.i.i6 = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__end1, i64 0, i32 176 store ptr %l4, ptr %__begin_.i.i.i.i6, align 877 %__end_.i.i.i.i7 = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__end1, i64 0, i32 278 store ptr %add.ptr.i5, ptr %__end_.i.i.i.i7, align 879 %cmp.not.i.i.i.i8 = icmp slt i64 %l5, 080 br i1 %cmp.not.i.i.i.i8, label %error, label %for.cond81 82error:83 call void @error()84 ret void85 86for.cond:87 %l8 = load ptr, ptr %__begin1, align 888 %l9 = load ptr, ptr %__end1, align 889 %cmp.i = icmp ne ptr %l8, %l990 br i1 %cmp.i, label %for.body, label %for.cond.cleanup91 92for.cond.cleanup: ; preds = %for.cond93 call void @llvm.lifetime.end.p0(ptr nonnull %__end1)94 call void @llvm.lifetime.end.p0(ptr nonnull %__begin1)95 ret void96 97for.body: ; preds = %for.cond98 %l10 = load ptr, ptr %__begin1, align 899 %__begin_.i.i = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__begin1, i64 0, i32 1100 %l11 = load ptr, ptr %__begin_.i.i, align 8101 %cmp.not.i.i = icmp uge ptr %l10, %l11102 %__end_.i.i = getelementptr inbounds %"struct.std::__1::__bounded_iter", ptr %__begin1, i64 0, i32 2103 %l12 = load ptr, ptr %__end_.i.i, align 8104 %cmp2.i.i = icmp ult ptr %l10, %l12105 %sel = select i1 %cmp.not.i.i, i1 %cmp2.i.i, i1 false106 br i1 %sel, label %for.latch, label %error107 108for.latch:109 call void @use(ptr noundef nonnull align 4 dereferenceable(4) %l10)110 %l = load ptr, ptr %__begin1, align 8111 %incdec.ptr.i = getelementptr inbounds i32, ptr %l, i64 1112 store ptr %incdec.ptr.i, ptr %__begin1, align 8113 br label %for.cond114}115 116declare void @error()117 118declare void @llvm.lifetime.start.p0(ptr nocapture)119 120declare void @use(ptr noundef nonnull align 4 dereferenceable(4))121 122declare void @llvm.lifetime.end.p0(ptr nocapture)123 124 125; -------------------------------------------------------------------------126; Test case for runtime check removal when accessing vector elements with127; hardened glibc++ (PR63125)128 129%Vector_base = type { %Vector_impl }130%Vector_impl = type { %Vector_impl_data }131%Vector_impl_data = type { ptr, ptr, ptr }132 133define void @foo(ptr noundef nonnull align 8 dereferenceable(24) noalias %vec) #0 {134; CHECK-LABEL: define void @foo(135; CHECK-SAME: ptr noalias noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[VEC:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {136; CHECK-NEXT: [[ENTRY:.*]]:137; CHECK-NEXT: [[_M_FINISH_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8138; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[_M_FINISH_I_I]], align 8, !tbaa [[ANYPTR_TBAA0:![0-9]+]]139; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC]], align 8, !tbaa [[ANYPTR_TBAA5:![0-9]+]]140; CHECK-NEXT: [[SUB_PTR_LHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP0]] to i64141; CHECK-NEXT: [[SUB_PTR_RHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP1]] to i64142; CHECK-NEXT: [[SUB_PTR_SUB_I_I:%.*]] = sub i64 [[SUB_PTR_LHS_CAST_I_I]], [[SUB_PTR_RHS_CAST_I_I]]143; CHECK-NEXT: [[SUB_PTR_DIV_I_I:%.*]] = ashr exact i64 [[SUB_PTR_SUB_I_I]], 3144; CHECK-NEXT: [[CMP_NOT9:%.*]] = icmp eq ptr [[TMP0]], [[TMP1]]145; CHECK-NEXT: br i1 [[CMP_NOT9]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY:.*]]146; CHECK: [[FOR_COND_CLEANUP]]:147; CHECK-NEXT: ret void148; CHECK: [[FOR_BODY]]:149; CHECK-NEXT: [[I_010:%.*]] = phi i64 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[ENTRY]] ]150; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds double, ptr [[TMP1]], i64 [[I_010]]151; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[ADD_PTR_I]], align 8152; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP2]], 1.000000e+00153; CHECK-NEXT: store double [[ADD]], ptr [[ADD_PTR_I]], align 8154; CHECK-NEXT: [[INC]] = add nuw i64 [[I_010]], 1155; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[INC]], [[SUB_PTR_DIV_I_I]]156; CHECK-NEXT: br i1 [[CMP_NOT]], label %[[FOR_COND_CLEANUP]], label %[[FOR_BODY]]157;158entry:159 %vec.addr = alloca ptr, align 8160 %count = alloca i64, align 8161 %i = alloca i64, align 8162 store ptr %vec, ptr %vec.addr, align 8163 call void @llvm.lifetime.start.p0(ptr %count)164 %0 = load ptr, ptr %vec.addr, align 8165 %call = call noundef i64 @alloc(ptr noundef nonnull align 8 dereferenceable(24) %0)166 store i64 %call, ptr %count, align 8167 call void @llvm.lifetime.start.p0(ptr %i)168 store i64 0, ptr %i, align 8169 br label %for.cond170 171for.cond:172 %1 = load i64, ptr %i, align 8173 %2 = load i64, ptr %count, align 8174 %cmp = icmp ne i64 %1, %2175 br i1 %cmp, label %for.body, label %for.cond.cleanup176 177for.cond.cleanup:178 call void @llvm.lifetime.end.p0(ptr %i)179 br label %for.end180 181for.body:182 %3 = load ptr, ptr %vec.addr, align 8183 %4 = load i64, ptr %i, align 8184 %call1 = call noundef nonnull align 8 dereferenceable(8) ptr @operator_acc(ptr noundef nonnull align 8 dereferenceable(24) %3, i64 noundef %4)185 %5 = load double, ptr %call1, align 8186 %add = fadd double %5, 1.000000e+00187 store double %add, ptr %call1, align 8188 br label %for.inc189 190for.inc:191 %6 = load i64, ptr %i, align 8192 %inc = add i64 %6, 1193 store i64 %inc, ptr %i, align 8194 br label %for.cond195 196for.end:197 call void @llvm.lifetime.end.p0(ptr %count) #5198 ret void199}200 201define internal noundef i64 @alloc(ptr noundef nonnull align 8 dereferenceable(24) %__cont) {202entry:203 %__cont.addr = alloca ptr, align 8204 store ptr %__cont, ptr %__cont.addr, align 8205 %0 = load ptr, ptr %__cont.addr, align 8206 %call = call noundef i64 @size(ptr noundef nonnull align 8 dereferenceable(24) %0) #5207 ret i64 %call208}209 210define internal noundef nonnull align 8 dereferenceable(8) ptr @operator_acc(ptr noundef nonnull align 8 dereferenceable(24) %this, i64 noundef %__n) {211entry:212 %this.addr = alloca ptr, align 8213 %__n.addr = alloca i64, align 8214 store ptr %this, ptr %this.addr, align 8215 store i64 %__n, ptr %__n.addr, align 8216 %this1 = load ptr, ptr %this.addr, align 8217 br label %do.body218 219do.body:220 %0 = load i64, ptr %__n.addr, align 8221 %call = call noundef i64 @size(ptr noundef nonnull align 8 dereferenceable(24) %this1)222 %cmp = icmp ult i64 %0, %call223 %lnot = xor i1 %cmp, true224 %conv = zext i1 %lnot to i64225 %tobool = icmp ne i64 %conv, 0226 br i1 %tobool, label %if.then, label %if.end227 228if.then:229 call void @abort() readnone230 unreachable231 232if.end:233 br label %do.cond234 235do.cond:236 br label %do.end237 238do.end:239 %_M_impl = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0240 %_M_start = getelementptr inbounds %Vector_impl_data, ptr %_M_impl, i32 0, i32 0241 %1 = load ptr, ptr %_M_start, align 8, !tbaa !0242 %2 = load i64, ptr %__n.addr, align 8, !tbaa !5243 %add.ptr = getelementptr inbounds double, ptr %1, i64 %2244 ret ptr %add.ptr245}246 247define internal noundef i64 @size(ptr noundef nonnull align 8 dereferenceable(24) %this) {248entry:249 %this.addr = alloca ptr, align 8250 store ptr %this, ptr %this.addr, align 8251 %this1 = load ptr, ptr %this.addr, align 8252 %_M_impl = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0253 %_M_finish = getelementptr inbounds %Vector_impl_data, ptr %_M_impl, i32 0, i32 1254 %0 = load ptr, ptr %_M_finish, align 8, !tbaa !7255 %_M_impl2 = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0256 %_M_start = getelementptr inbounds %Vector_impl_data, ptr %_M_impl2, i32 0, i32 0257 %1 = load ptr, ptr %_M_start, align 8, !tbaa !0258 %sub.ptr.lhs.cast = ptrtoint ptr %0 to i64259 %sub.ptr.rhs.cast = ptrtoint ptr %1 to i64260 %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast261 %sub.ptr.div = sdiv exact i64 %sub.ptr.sub, 8262 ret i64 %sub.ptr.div263}264 265declare void @abort()266 267; -------------------------------------------------------------------------268; Test case for runtime check removal when accessing vector elements with269; hardened glibc++ and a signed induction variable.270; https://github.com/llvm/llvm-project/issues/63126271 272define void @loop_with_signed_induction(ptr noundef nonnull align 8 dereferenceable(24) %vec) {273; CHECK-LABEL: define void @loop_with_signed_induction(274; CHECK-SAME: ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[VEC:%.*]]) local_unnamed_addr #[[ATTR0]] {275; CHECK-NEXT: [[ENTRY:.*]]:276; CHECK-NEXT: [[_M_FINISH_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8277; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[_M_FINISH_I_I]], align 8, !tbaa [[ANYPTR_TBAA0]]278; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC]], align 8, !tbaa [[ANYPTR_TBAA5]]279; CHECK-NEXT: [[SUB_PTR_LHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP0]] to i64280; CHECK-NEXT: [[SUB_PTR_RHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP1]] to i64281; CHECK-NEXT: [[SUB_PTR_SUB_I_I:%.*]] = sub i64 [[SUB_PTR_LHS_CAST_I_I]], [[SUB_PTR_RHS_CAST_I_I]]282; CHECK-NEXT: [[SUB_PTR_DIV_I_I:%.*]] = ashr exact i64 [[SUB_PTR_SUB_I_I]], 3283; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt i64 [[SUB_PTR_DIV_I_I]], 0284; CHECK-NEXT: br i1 [[CMP9]], label %[[FOR_BODY:.*]], label %[[FOR_COND_CLEANUP:.*]]285; CHECK: [[FOR_COND_CLEANUP]]:286; CHECK-NEXT: ret void287; CHECK: [[FOR_BODY]]:288; CHECK-NEXT: [[I_010:%.*]] = phi i64 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[ENTRY]] ]289; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds nuw double, ptr [[TMP1]], i64 [[I_010]]290; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[ADD_PTR_I]], align 8, !tbaa [[DOUBLE_TBAA6:![0-9]+]]291; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP2]], 1.000000e+00292; CHECK-NEXT: store double [[ADD]], ptr [[ADD_PTR_I]], align 8, !tbaa [[DOUBLE_TBAA6]]293; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_010]], 1294; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], [[SUB_PTR_DIV_I_I]]295; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_COND_CLEANUP]]296;297entry:298 %vec.addr = alloca ptr, align 8299 %count = alloca i64, align 8300 %i = alloca i64, align 8301 store ptr %vec, ptr %vec.addr, align 8302 call void @llvm.lifetime.start.p0(ptr %count)303 %0 = load ptr, ptr %vec.addr, align 8304 %call = call noundef i64 @alloc(ptr noundef nonnull align 8 dereferenceable(24) %0)305 store i64 %call, ptr %count, align 8306 call void @llvm.lifetime.start.p0(ptr %i)307 store i64 0, ptr %i, align 8308 br label %for.cond309 310for.cond:311 %1 = load i64, ptr %i, align 8312 %2 = load i64, ptr %count, align 8313 %cmp = icmp slt i64 %1, %2314 br i1 %cmp, label %for.body, label %for.cond.cleanup315 316for.cond.cleanup:317 call void @llvm.lifetime.end.p0(ptr %i)318 br label %for.end319 320for.body:321 %3 = load ptr, ptr %vec.addr, align 8322 %4 = load i64, ptr %i, align 8323 %call1 = call noundef nonnull align 8 dereferenceable(8) ptr @operator_acc(ptr noundef nonnull align 8 dereferenceable(24) %3, i64 noundef %4)324 %5 = load double, ptr %call1, align 8, !tbaa !8325 %add = fadd double %5, 1.000000e+00326 store double %add, ptr %call1, align 8, !tbaa !8327 br label %for.inc328 329for.inc:330 %6 = load i64, ptr %i, align 8331 %inc = add nsw i64 %6, 1332 store i64 %inc, ptr %i, align 8333 br label %for.cond334 335for.end:336 call void @llvm.lifetime.end.p0(ptr %count)337 ret void338}339 340; -------------------------------------------------------------------------341; Test case for runtime check removal when accessing elements in a nested loop342; (PR64881)343 344 345define void @monkey(ptr noundef %arr, i32 noundef %len) {346; CHECK-LABEL: define void @monkey(347; CHECK-SAME: ptr noundef captures(none) [[ARR:%.*]], i32 noundef [[LEN:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {348; CHECK-NEXT: [[ENTRY:.*]]:349; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt i32 [[LEN]], 1350; CHECK-NEXT: br i1 [[CMP8]], label %[[FOR_BODY4_PREHEADER:.*]], label %[[FOR_COND_CLEANUP:.*]]351; CHECK: [[FOR_BODY4_PREHEADER]]:352; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ [[INC:%.*]], %[[FOR_COND_CLEANUP3:.*]] ], [ 1, %[[ENTRY]] ]353; CHECK-NEXT: br label %[[FOR_BODY4:.*]]354; CHECK: [[FOR_COND_CLEANUP]]:355; CHECK-NEXT: ret void356; CHECK: [[FOR_COND_CLEANUP3]]:357; CHECK-NEXT: [[INC]] = add nuw i32 [[I_09]], 1358; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC]], [[LEN]]359; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY4_PREHEADER]], label %[[FOR_COND_CLEANUP]]360; CHECK: [[FOR_BODY4]]:361; CHECK-NEXT: [[K_07:%.*]] = phi i32 [ [[DEC:%.*]], %[[FOR_BODY4]] ], [ [[I_09]], %[[FOR_BODY4_PREHEADER]] ]362; CHECK-NEXT: [[IDX_EXT_I:%.*]] = zext i32 [[K_07]] to i64363; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds nuw i32, ptr [[ARR]], i64 [[IDX_EXT_I]]364; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4365; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1366; CHECK-NEXT: store i32 [[ADD]], ptr [[ADD_PTR_I]], align 4367; CHECK-NEXT: [[DEC]] = add i32 [[K_07]], -1368; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i32 [[DEC]], 0369; CHECK-NEXT: br i1 [[CMP2_NOT]], label %[[FOR_COND_CLEANUP3]], label %[[FOR_BODY4]]370;371entry:372 %arr.addr = alloca ptr, align 8373 %len.addr = alloca i32, align 4374 %i = alloca i32, align 4375 %cleanup.dest.slot = alloca i32, align 4376 %k = alloca i32, align 4377 store ptr %arr, ptr %arr.addr, align 8378 store i32 %len, ptr %len.addr, align 4379 call void @llvm.lifetime.start.p0(ptr %i) #3380 store i32 1, ptr %i, align 4381 br label %for.cond382 383for.cond: ; preds = %for.inc5, %entry384 %0 = load i32, ptr %i, align 4385 %1 = load i32, ptr %len.addr, align 4386 %cmp = icmp ult i32 %0, %1387 br i1 %cmp, label %for.body, label %for.cond.cleanup388 389for.cond.cleanup: ; preds = %for.cond390 store i32 2, ptr %cleanup.dest.slot, align 4391 call void @llvm.lifetime.end.p0(ptr %i) #3392 br label %for.end6393 394for.body: ; preds = %for.cond395 call void @llvm.lifetime.start.p0(ptr %k) #3396 %2 = load i32, ptr %i, align 4397 store i32 %2, ptr %k, align 4398 br label %for.cond1399 400for.cond1: ; preds = %for.inc, %for.body401 %3 = load i32, ptr %k, align 4402 %cmp2 = icmp ugt i32 %3, 0403 br i1 %cmp2, label %for.body4, label %for.cond.cleanup3404 405for.cond.cleanup3: ; preds = %for.cond1406 store i32 5, ptr %cleanup.dest.slot, align 4407 call void @llvm.lifetime.end.p0(ptr %k) #3408 br label %for.end409 410for.body4: ; preds = %for.cond1411 %4 = load ptr, ptr %arr.addr, align 8412 %5 = load i32, ptr %len.addr, align 4413 %6 = load i32, ptr %k, align 4414 %call = call noundef ptr @at(ptr noundef %4, i32 noundef %5, i32 noundef %6)415 %7 = load i32, ptr %call, align 4416 %add = add nsw i32 %7, 1417 store i32 %add, ptr %call, align 4418 br label %for.inc419 420for.inc: ; preds = %for.body4421 %8 = load i32, ptr %k, align 4422 %dec = add i32 %8, -1423 store i32 %dec, ptr %k, align 4424 br label %for.cond1425 426for.end: ; preds = %for.cond.cleanup3427 br label %for.inc5428 429for.inc5: ; preds = %for.end430 %9 = load i32, ptr %i, align 4431 %inc = add i32 %9, 1432 store i32 %inc, ptr %i, align 4433 br label %for.cond434 435for.end6: ; preds = %for.cond.cleanup436 ret void437}438 439define internal noundef ptr @at(ptr noundef %arr, i32 noundef %len, i32 noundef %idx) {440entry:441 %arr.addr = alloca ptr, align 8442 %len.addr = alloca i32, align 4443 %idx.addr = alloca i32, align 4444 store ptr %arr, ptr %arr.addr, align 8445 store i32 %len, ptr %len.addr, align 4446 store i32 %idx, ptr %idx.addr, align 4447 %0 = load i32, ptr %idx.addr, align 4448 %1 = load i32, ptr %len.addr, align 4449 %cmp = icmp uge i32 %0, %1450 br i1 %cmp, label %if.then, label %if.end451 452if.then: ; preds = %entry453 call void @abort()454 unreachable455 456if.end: ; preds = %entry457 %2 = load ptr, ptr %arr.addr, align 8458 %3 = load i32, ptr %idx.addr, align 4459 %idx.ext = zext i32 %3 to i64460 %add.ptr = getelementptr inbounds i32, ptr %2, i64 %idx.ext461 ret ptr %add.ptr462}463 464 465!0 = !{!1, !2, i64 0}466!1 = !{!"_ZTSNSt12_Vector_baseIdSaIdEE17_Vector_impl_dataE", !2, i64 0, !2, i64 8, !2, i64 16}467!2 = !{!"any pointer", !3, i64 0}468!3 = !{!"omnipotent char", !4, i64 0}469!4 = !{!"Simple C++ TBAA"}470!5 = !{!6, !6, i64 0}471!6 = !{!"long", !3, i64 0}472!7 = !{!1, !2, i64 8}473!8 = !{!9, !9, i64 0}474!9 = !{!"double", !3, i64 0}475;.476; CHECK: [[ANYPTR_TBAA0]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]], i64 8}477; CHECK: [[META1]] = !{!"_ZTSNSt12_Vector_baseIdSaIdEE17_Vector_impl_dataE", [[META2]], i64 0, [[META2]], i64 8, [[META2]], i64 16}478; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0}479; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}480; CHECK: [[META4]] = !{!"Simple C++ TBAA"}481; CHECK: [[ANYPTR_TBAA5]] = !{[[META1]], [[META2]], i64 0}482; CHECK: [[DOUBLE_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}483; CHECK: [[META7]] = !{!"double", [[META3]], i64 0}484;.485