136 lines
5.6 KiB
LLVM
136 lines
5.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes="loop-reduce" -S -lsr-term-fold | FileCheck %s
|
|
|
|
; There are 3 test cases here regarding the replacing the primary iv with
|
|
; other affine AddRec IV.
|
|
; 1. Loop with constant tripcount
|
|
; 2. Loop with runtime tripcount
|
|
; 3. The replacing AddRec IV is a complicated AddRec. This tests whether
|
|
; the fold terminating condition transformation is writing new terminating
|
|
; condition in the correct type.
|
|
|
|
target datalayout = "e-p:32:32:32-n32"
|
|
|
|
; This is equivalent to the following code, loop guard is removed.
|
|
; void const_tripcount(int *a) {
|
|
; for (int i = 21; i < 400; i++)
|
|
; a[i] = 1;
|
|
; }
|
|
define void @const_tripcount(ptr %a) {
|
|
; CHECK-LABEL: @const_tripcount(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
|
|
; CHECK-NEXT: [[UGLYGEP1:%.*]] = getelementptr i8, ptr [[A]], i32 1600
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4
|
|
; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
|
|
; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[UGLYGEP1]]
|
|
; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], 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
|
|
}
|
|
|
|
; This is equivalent to the following code, loop guard is removed.
|
|
; void runtime_tripcount(int *a, int N) {
|
|
; for (int i = 21; i < N; i++)
|
|
; a[i] = 1;
|
|
; }
|
|
|
|
define void @runtime_tripcount(ptr %a, i32 %N) {
|
|
; CHECK-LABEL: @runtime_tripcount(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
|
|
; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[N:%.*]], 2
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 84
|
|
; CHECK-NEXT: [[UGLYGEP1:%.*]] = getelementptr i8, ptr [[A]], i32 [[TMP1]]
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4
|
|
; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
|
|
; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[UGLYGEP1]]
|
|
; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%uglygep = getelementptr i8, ptr %a, i32 84
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body, %entry
|
|
%lsr.iv1 = phi ptr [ %uglygep2, %for.body ], [ %uglygep, %entry ]
|
|
%lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ %N, %entry ]
|
|
store i32 1, ptr %lsr.iv1, align 4
|
|
%lsr.iv.next = add nsw i32 %lsr.iv, -1
|
|
%uglygep2 = getelementptr i8, ptr %lsr.iv1, i64 4
|
|
%exitcond.not = icmp eq i32 %lsr.iv.next, 0
|
|
br i1 %exitcond.not, label %for.end, label %for.body
|
|
|
|
for.end: ; preds = %for.body
|
|
ret void
|
|
}
|
|
|
|
; This is modified from IR of the following code, loop guard is removed.
|
|
; void foo(int*);
|
|
; void ptr_of_ptr_addrec(int **ptrptr, int length) {
|
|
; int **it = ptrptr;
|
|
; for (int i = length; i; i--) {
|
|
; foo(*it);
|
|
; it++;
|
|
; }
|
|
; }
|
|
define void @ptr_of_ptr_addrec(ptr %ptrptr, i32 %length) {
|
|
; CHECK-LABEL: @ptr_of_ptr_addrec(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTRPTR:%.*]] = getelementptr ptr, ptr [[PTRPTR:%.*]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[LENGTH:%.*]], 2
|
|
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[START_PTRPTR]], i32 [[TMP0]]
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IT_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[START_PTRPTR]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IT_04]], align 8
|
|
; CHECK-NEXT: tail call void @foo(ptr [[TMP1]])
|
|
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds ptr, ptr [[IT_04]], i64 1
|
|
; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[UGLYGEP]]
|
|
; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start.ptrptr = getelementptr inbounds ptr, ptr %ptrptr
|
|
br label %for.body
|
|
|
|
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.end, label %for.body
|
|
|
|
for.end: ; preds = %for.body
|
|
ret void
|
|
}
|
|
|
|
declare void @foo(ptr)
|