blob: 752d8b86012e4de1f32bf5585534152f1eff5cf1 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes="loop-simplify,simplifycfg<no-keep-loops>,loop-unroll" < %s | FileCheck %s --check-prefix=UNROLL
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes="loop-simplify,simplifycfg<no-keep-loops>,loop-vectorize" < %s | FileCheck %s --check-prefix=VECTORIZE
; SimplifyCFG without canonical loops folds the unique backedge block inserted
; by LoopSimplify. The loop unroller and the vectorizer re-simplify the loop
; and must not separate it into a nested loop on a target with branch
; divergence either.
define i32 @continue_loop(i32 %n, ptr %p) {
; UNROLL-LABEL: define i32 @continue_loop(
; UNROLL-SAME: i32 [[N:%.*]], ptr [[P:%.*]]) {
; UNROLL-NEXT: [[ENTRY:.*]]:
; UNROLL-NEXT: [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
; UNROLL-NEXT: br label %[[HEADER:.*]]
; UNROLL: [[HEADER]]:
; UNROLL-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[HEADER_BACKEDGE:.*]] ]
; UNROLL-NEXT: [[ACC:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[ACC_BE:%.*]], %[[HEADER_BACKEDGE]] ]
; UNROLL-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; UNROLL-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[P]], i32 [[I]]
; UNROLL-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
; UNROLL-NEXT: [[BITS:%.*]] = lshr i32 [[V]], [[TID]]
; UNROLL-NEXT: [[BIT:%.*]] = and i32 [[BITS]], 1
; UNROLL-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[BIT]], 0
; UNROLL-NEXT: br i1 [[IS_ZERO]], label %[[CONTINUE:.*]], label %[[UPDATE:.*]]
; UNROLL: [[CONTINUE]]:
; UNROLL-NEXT: [[C1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; UNROLL-NEXT: br i1 [[C1]], label %[[HEADER_BACKEDGE]], label %[[EXIT:.*]]
; UNROLL: [[HEADER_BACKEDGE]]:
; UNROLL-NEXT: [[ACC_BE]] = phi i32 [ [[ACC]], %[[CONTINUE]] ], [ [[ACC_NEXT:%.*]], %[[UPDATE]] ]
; UNROLL-NEXT: br label %[[HEADER]]
; UNROLL: [[UPDATE]]:
; UNROLL-NEXT: [[ACC_NEXT]] = add i32 [[ACC]], [[V]]
; UNROLL-NEXT: [[C2:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; UNROLL-NEXT: br i1 [[C2]], label %[[HEADER_BACKEDGE]], label %[[EXIT]]
; UNROLL: [[EXIT]]:
; UNROLL-NEXT: [[R:%.*]] = phi i32 [ [[ACC]], %[[CONTINUE]] ], [ [[ACC_NEXT]], %[[UPDATE]] ]
; UNROLL-NEXT: ret i32 [[R]]
;
; VECTORIZE-LABEL: define i32 @continue_loop(
; VECTORIZE-SAME: i32 [[N:%.*]], ptr [[P:%.*]]) {
; VECTORIZE-NEXT: [[ENTRY:.*]]:
; VECTORIZE-NEXT: [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
; VECTORIZE-NEXT: br label %[[HEADER:.*]]
; VECTORIZE: [[HEADER]]:
; VECTORIZE-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[HEADER_BACKEDGE:.*]] ]
; VECTORIZE-NEXT: [[ACC:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[ACC_BE:%.*]], %[[HEADER_BACKEDGE]] ]
; VECTORIZE-NEXT: [[I_NEXT]] = add i32 [[I]], 1
; VECTORIZE-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[P]], i32 [[I]]
; VECTORIZE-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
; VECTORIZE-NEXT: [[BITS:%.*]] = lshr i32 [[V]], [[TID]]
; VECTORIZE-NEXT: [[BIT:%.*]] = and i32 [[BITS]], 1
; VECTORIZE-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[BIT]], 0
; VECTORIZE-NEXT: br i1 [[IS_ZERO]], label %[[CONTINUE:.*]], label %[[UPDATE:.*]]
; VECTORIZE: [[CONTINUE]]:
; VECTORIZE-NEXT: [[C1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; VECTORIZE-NEXT: br i1 [[C1]], label %[[HEADER_BACKEDGE]], label %[[EXIT:.*]]
; VECTORIZE: [[HEADER_BACKEDGE]]:
; VECTORIZE-NEXT: [[ACC_BE]] = phi i32 [ [[ACC]], %[[CONTINUE]] ], [ [[ACC_NEXT:%.*]], %[[UPDATE]] ]
; VECTORIZE-NEXT: br label %[[HEADER]]
; VECTORIZE: [[UPDATE]]:
; VECTORIZE-NEXT: [[ACC_NEXT]] = add i32 [[ACC]], [[V]]
; VECTORIZE-NEXT: [[C2:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; VECTORIZE-NEXT: br i1 [[C2]], label %[[HEADER_BACKEDGE]], label %[[EXIT]]
; VECTORIZE: [[EXIT]]:
; VECTORIZE-NEXT: [[R:%.*]] = phi i32 [ [[ACC]], %[[CONTINUE]] ], [ [[ACC_NEXT]], %[[UPDATE]] ]
; VECTORIZE-NEXT: ret i32 [[R]]
;
entry:
%tid = call i32 @llvm.amdgcn.workitem.id.x()
br label %header
header:
%i = phi i32 [ 0, %entry ], [ %i.next, %continue ], [ %i.next, %update ]
%acc = phi i32 [ 0, %entry ], [ %acc, %continue ], [ %acc.next, %update ]
%i.next = add i32 %i, 1
%gep = getelementptr i32, ptr %p, i32 %i
%v = load i32, ptr %gep, align 4
%bits = lshr i32 %v, %tid
%bit = and i32 %bits, 1
%is.zero = icmp eq i32 %bit, 0
br i1 %is.zero, label %continue, label %update
continue:
%c1 = icmp slt i32 %i.next, %n
br i1 %c1, label %header, label %exit
update:
%acc.next = add i32 %acc, %v
%c2 = icmp slt i32 %i.next, %n
br i1 %c2, label %header, label %exit
exit:
%r = phi i32 [ %acc, %continue ], [ %acc.next, %update ]
ret i32 %r
}
declare i32 @llvm.amdgcn.workitem.id.x()