diff --git a/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-complicate-add-rec.ll b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-complicate-add-rec.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-complicate-add-rec.ll @@ -0,0 +1,50 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes="loop-reduce" -S | FileCheck %s +; This is compiled from the following code +; void foo(int*); +; void ptr_of_ptr_addrec(int **ptrptr, int length) { +; int **it = ptrptr; +; for (int i = length; i; i--) { +; foo(*it); +; it++; +; } +; } + +target datalayout = "e-p:32:32:32-n32" + +define void @ptr_of_ptr_addrec(ptr %ptrptr, i32 %length) { +; CHECK-LABEL: @ptr_of_ptr_addrec( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[START_PTRPTR:%.*]] = getelementptr inbounds ptr, ptr [[PTRPTR:%.*]] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[DEC:%.*]], [[FOR_BODY]] ], [ [[LENGTH:%.*]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[IT_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[START_PTRPTR]], [[ENTRY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[IT_04]], align 8 +; CHECK-NEXT: tail call void @foo(ptr [[TMP0]]) +; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds ptr, ptr [[IT_04]], i64 1 +; CHECK-NEXT: [[DEC]] = add i32 [[I_05]], -1 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[DEC]], 0 +; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; +entry: + %start.ptrptr = getelementptr inbounds ptr, ptr %ptrptr + br label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + ret void + +for.body: ; preds = %entry, %for.body + %i.05 = phi i32 [ %dec, %for.body ], [ %length, %entry ] + %it.04 = phi ptr [ %incdec.ptr, %for.body ], [ %start.ptrptr, %entry ] + %0 = load ptr, ptr %it.04, align 8 + tail call void @foo(ptr %0) + %incdec.ptr = getelementptr inbounds ptr, ptr %it.04, i64 1 + %dec = add nsw i32 %i.05, -1 + %tobool.not = icmp eq i32 %dec, 0 + br i1 %tobool.not, label %for.cond.cleanup, label %for.body +} + +declare void @foo(ptr) diff --git a/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-const-tripcount.ll b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-const-tripcount.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-const-tripcount.ll @@ -0,0 +1,42 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes="loop-reduce" -S | FileCheck %s +; This is compiled from the following code +; void close_bubbles(int a[400]) { +; for (int i = 21; i < 400; i++) +; a[i] = 1; +; } + +target datalayout = "e-p:32:32:32-n32" + +define void @close_bubbles(ptr %a) { +; CHECK-LABEL: @close_bubbles( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 379, [[ENTRY]] ] +; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], -1 +; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + %uglygep = getelementptr i8, ptr %a, i64 84 + br label %for.body + +for.body: ; preds = %for.body, %entry + %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ] + %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ 379, %entry ] + store i32 1, ptr %lsr.iv1, align 4 + %lsr.iv.next = add nsw i64 %lsr.iv, -1 + %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4 + %exitcond.not = icmp eq i64 %lsr.iv.next, 0 + br i1 %exitcond.not, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} diff --git a/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-runtime-tripcount.ll b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-runtime-tripcount.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/lsr-fold-iv-runtime-tripcount.ll @@ -0,0 +1,66 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes="loop-reduce" -S | FileCheck %s +; This is compiled from the following code +; void foo(char*); +; void runtime_tripcount(char *seq, int L) +; { +; for (int i = 1; i <= L; i++) +; foo(seq); +; } + +target datalayout = "e-p:32:32:32-n32" + +define void @runtime_tripcount(ptr %seq, i32 %L) { +; CHECK-LABEL: @runtime_tripcount( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP_NOT3:%.*]] = icmp slt i32 [[L:%.*]], 1 +; CHECK-NEXT: br i1 [[CMP_NOT3]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[L]], 1 +; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 +; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[SEQ:%.*]], i64 1 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP1]], [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[LSR_IV1]], align 1 +; CHECK-NEXT: tail call void @foo(i8 noundef zeroext [[TMP2]]) +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], -1 +; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 1 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; +entry: + %cmp.not3 = icmp slt i32 %L, 1 + br i1 %cmp.not3, label %for.cond.cleanup, label %for.body.preheader + +for.body.preheader: ; preds = %entry + %0 = add nuw i32 %L, 1 + %wide.trip.count = zext i32 %0 to i64 + %1 = add nsw i64 %wide.trip.count, -1 + %uglygep = getelementptr i8, ptr %seq, i64 1 + br label %for.body + +for.cond.cleanup.loopexit: ; preds = %for.body + br label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry + ret void + +for.body: ; preds = %for.body, %for.body.preheader + %lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %for.body.preheader ] + %lsr.iv = phi i64 [ %lsr.iv.next, %for.body ], [ %1, %for.body.preheader ] + %2 = load i8, ptr %lsr.iv1, align 1 + tail call void @foo(i8 noundef zeroext %2) #2 + %lsr.iv.next = add nsw i64 %lsr.iv, -1 + %uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 1 + %exitcond.not = icmp eq i64 %lsr.iv.next, 0 + br i1 %exitcond.not, label %for.cond.cleanup.loopexit, label %for.body +} + +declare void @foo(i8)