; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -p loop-idiom -S %s | FileCheck %s define void @fold_add_zext_to_sext(ptr %dst, i1 %start) { ; CHECK-LABEL: define void @fold_add_zext_to_sext( ; CHECK-SAME: ptr [[DST:%.*]], i1 [[START:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[START_EXT:%.*]] = zext i1 [[START]] to i32 ; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[START]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2 ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = shl nuw nsw i32 [[START_EXT]], 2 ; CHECK-NEXT: [[TMP2:%.*]] = sub i32 100, [[TMP4]] ; CHECK-NEXT: [[TMP3:%.*]] = zext nneg i32 [[TMP2]] to i64 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[SCEVGEP]], i8 0, i64 [[TMP3]], i1 false) ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START_EXT]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[IV_EXT:%.*]] = zext i32 [[IV]] to i64 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[DST]], i64 [[IV_EXT]] ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp ult i32 [[IV]], 24 ; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret void ; entry: %start.ext = zext i1 %start to i32 br label %loop loop: %iv = phi i32 [ %start.ext, %entry ], [ %iv.next, %loop ] %iv.ext = zext i32 %iv to i64 %gep = getelementptr i32, ptr %dst, i64 %iv.ext store i32 0, ptr %gep, align 4 %iv.next = add i32 %iv, 1 %ec = icmp ult i32 %iv, 24 br i1 %ec, label %loop, label %exit exit: ret void } declare i16 @get() define void @test_memset_size_can_use_info_from_guards(i32 %x, ptr %dst) { ; CHECK-LABEL: define void @test_memset_size_can_use_info_from_guards( ; CHECK-SAME: i32 [[X:%.*]], ptr [[DST:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[LOOP1:.*]] ; CHECK: [[LOOP1_LOOPEXIT:.*]]: ; CHECK-NEXT: br label %[[LOOP1_BACKEDGE:.*]] ; CHECK: [[LOOP1]]: ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[X]], %[[LOOP1_BACKEDGE]] ] ; CHECK-NEXT: [[L:%.*]] = call i16 @get() ; CHECK-NEXT: [[L_EXT:%.*]] = zext i16 [[L]] to i32 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[L_EXT]], [[P]] ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[SUB]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp ult i32 [[SUB]], 2 ; CHECK-NEXT: br i1 [[EC]], label %[[LOOP1_BACKEDGE]], label %[[LOOP2_PREHEADER:.*]] ; CHECK: [[LOOP1_BACKEDGE]]: ; CHECK-NEXT: br label %[[LOOP1]] ; CHECK: [[LOOP2_PREHEADER]]: ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[SUB]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 1 ; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP1]], i64 1) ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[DST]], i8 0, i64 [[UMAX]], i1 false) ; CHECK-NEXT: br label %[[LOOP2:.*]] ; CHECK: [[LOOP2]]: ; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_2_NEXT:%.*]], %[[LOOP2]] ], [ 0, %[[LOOP2_PREHEADER]] ] ; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr i8, ptr [[DST]], i32 [[IV_2]] ; CHECK-NEXT: [[IV_2_NEXT]] = add i32 [[IV_2]], 1 ; CHECK-NEXT: [[EC_2:%.*]] = icmp ult i32 [[IV_2_NEXT]], [[SHR]] ; CHECK-NEXT: br i1 [[EC_2]], label %[[LOOP2]], label %[[LOOP1_LOOPEXIT]] ; entry: br label %loop1 loop1: %p = phi i32 [ 0, %entry ], [ %x, %loop1 ], [ %x, %loop2 ] %l = call i16 @get() %l.ext = zext i16 %l to i32 %sub = sub i32 %l.ext, %p %shr = lshr i32 %sub, 1 %ec = icmp ult i32 %sub, 2 br i1 %ec, label %loop1, label %loop2 loop2: %iv.2 = phi i32 [ 0, %loop1 ], [ %iv.2.next, %loop2 ] %gep.dst = getelementptr i8, ptr %dst, i32 %iv.2 store i8 0, ptr %gep.dst, align 1 %iv.2.next = add i32 %iv.2, 1 %ec.2 = icmp ult i32 %iv.2.next, %shr br i1 %ec.2, label %loop2, label %loop1 }