blob: 33b3415d36b6d80ab95f395cf98d6e2fb46a7dec [file] [edit]
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
// A standalone `#pragma omp tile` keeps the intra-tile loop min-bounded: the
// upper bound `min(.floor.iv + tilesize, N)` is materialized as a
// cond.true/cond.false/phi and there is no body guard. The guarded rectangular
// form appears only once a directive consumes the tile, see
// tile_collapse_reinterpret_codegen.cpp.
//
// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm -o - %s | FileCheck %s --check-prefix=IR
// expected-no-diagnostics
extern "C" void body(int);
// Trip count 6, tile 4: the last tile is partial, and the min() bound alone
// stops it at the trip count.
// IR-LABEL: define dso_local void @_Z18remainder_6_tile_4v(
// IR-SAME: ) #[[ATTR0:[0-9]+]] {
// IR-NEXT: [[ENTRY:.*:]]
// IR-NEXT: [[I:%.*]] = alloca i32, align 4
// IR-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4
// IR-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4
// IR-NEXT: store i32 0, ptr [[I]], align 4
// IR-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND:.*]]
// IR: [[FOR_COND]]:
// IR-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 6
// IR-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END9:.*]]
// IR: [[FOR_BODY]]:
// IR-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: store i32 [[TMP1]], ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND1:.*]]
// IR: [[FOR_COND1]]:
// IR-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 4
// IR-NEXT: [[CMP2:%.*]] = icmp slt i32 6, [[ADD]]
// IR-NEXT: br i1 [[CMP2]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
// IR: [[COND_TRUE]]:
// IR-NEXT: br label %[[COND_END:.*]]
// IR: [[COND_FALSE]]:
// IR-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD3:%.*]] = add nsw i32 [[TMP4]], 4
// IR-NEXT: br label %[[COND_END]]
// IR: [[COND_END]]:
// IR-NEXT: [[COND:%.*]] = phi i32 [ 6, %[[COND_TRUE]] ], [ [[ADD3]], %[[COND_FALSE]] ]
// IR-NEXT: [[CMP4:%.*]] = icmp slt i32 [[TMP2]], [[COND]]
// IR-NEXT: br i1 [[CMP4]], label %[[FOR_BODY5:.*]], label %[[FOR_END:.*]]
// IR: [[FOR_BODY5]]:
// IR-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP5]], 1
// IR-NEXT: [[ADD6:%.*]] = add nsw i32 0, [[MUL]]
// IR-NEXT: store i32 [[ADD6]], ptr [[I]], align 4
// IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[I]], align 4
// IR-NEXT: call void @body(i32 noundef [[TMP6]])
// IR-NEXT: br label %[[FOR_INC:.*]]
// IR: [[FOR_INC]]:
// IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[INC:%.*]] = add nsw i32 [[TMP7]], 1
// IR-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND1]], !llvm.loop [[LOOP2:![0-9]+]]
// IR: [[FOR_END]]:
// IR-NEXT: br label %[[FOR_INC7:.*]]
// IR: [[FOR_INC7]]:
// IR-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD8:%.*]] = add nsw i32 [[TMP8]], 4
// IR-NEXT: store i32 [[ADD8]], ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]]
// IR: [[FOR_END9]]:
// IR-NEXT: ret void
//
void remainder_6_tile_4(void) {
#pragma omp tile sizes(4)
for (int i = 0; i < 6; ++i)
body(i);
}
// The inner `j` loop is not one of the tiled loops, so it is emitted untouched
// inside the intra-tile loop.
// IR-LABEL: define dso_local void @_Z14nested_inner_ji(
// IR-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] {
// IR-NEXT: [[ENTRY:.*:]]
// IR-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
// IR-NEXT: [[I:%.*]] = alloca i32, align 4
// IR-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4
// IR-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4
// IR-NEXT: [[J:%.*]] = alloca i32, align 4
// IR-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
// IR-NEXT: store i32 0, ptr [[I]], align 4
// IR-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND:.*]]
// IR: [[FOR_COND]]:
// IR-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 6
// IR-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END16:.*]]
// IR: [[FOR_BODY]]:
// IR-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: store i32 [[TMP1]], ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND1:.*]]
// IR: [[FOR_COND1]]:
// IR-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 4
// IR-NEXT: [[CMP2:%.*]] = icmp slt i32 6, [[ADD]]
// IR-NEXT: br i1 [[CMP2]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]
// IR: [[COND_TRUE]]:
// IR-NEXT: br label %[[COND_END:.*]]
// IR: [[COND_FALSE]]:
// IR-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD3:%.*]] = add nsw i32 [[TMP4]], 4
// IR-NEXT: br label %[[COND_END]]
// IR: [[COND_END]]:
// IR-NEXT: [[COND:%.*]] = phi i32 [ 6, %[[COND_TRUE]] ], [ [[ADD3]], %[[COND_FALSE]] ]
// IR-NEXT: [[CMP4:%.*]] = icmp slt i32 [[TMP2]], [[COND]]
// IR-NEXT: br i1 [[CMP4]], label %[[FOR_BODY5:.*]], label %[[FOR_END13:.*]]
// IR: [[FOR_BODY5]]:
// IR-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP5]], 1
// IR-NEXT: [[ADD6:%.*]] = add nsw i32 0, [[MUL]]
// IR-NEXT: store i32 [[ADD6]], ptr [[I]], align 4
// IR-NEXT: store i32 0, ptr [[J]], align 4
// IR-NEXT: br label %[[FOR_COND7:.*]]
// IR: [[FOR_COND7]]:
// IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[J]], align 4
// IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[N_ADDR]], align 4
// IR-NEXT: [[CMP8:%.*]] = icmp slt i32 [[TMP6]], [[TMP7]]
// IR-NEXT: br i1 [[CMP8]], label %[[FOR_BODY9:.*]], label %[[FOR_END:.*]]
// IR: [[FOR_BODY9]]:
// IR-NEXT: [[TMP8:%.*]] = load i32, ptr [[I]], align 4
// IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[J]], align 4
// IR-NEXT: [[ADD10:%.*]] = add nsw i32 [[TMP8]], [[TMP9]]
// IR-NEXT: call void @body(i32 noundef [[ADD10]])
// IR-NEXT: br label %[[FOR_INC:.*]]
// IR: [[FOR_INC]]:
// IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[J]], align 4
// IR-NEXT: [[INC:%.*]] = add nsw i32 [[TMP10]], 1
// IR-NEXT: store i32 [[INC]], ptr [[J]], align 4
// IR-NEXT: br label %[[FOR_COND7]], !llvm.loop [[LOOP5:![0-9]+]]
// IR: [[FOR_END]]:
// IR-NEXT: br label %[[FOR_INC11:.*]]
// IR: [[FOR_INC11]]:
// IR-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: [[INC12:%.*]] = add nsw i32 [[TMP11]], 1
// IR-NEXT: store i32 [[INC12]], ptr [[DOTTILE_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND1]], !llvm.loop [[LOOP6:![0-9]+]]
// IR: [[FOR_END13]]:
// IR-NEXT: br label %[[FOR_INC14:.*]]
// IR: [[FOR_INC14]]:
// IR-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: [[ADD15:%.*]] = add nsw i32 [[TMP12]], 4
// IR-NEXT: store i32 [[ADD15]], ptr [[DOTFLOOR_0_IV_I]], align 4
// IR-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]]
// IR: [[FOR_END16]]:
// IR-NEXT: ret void
//
void nested_inner_j(int n) {
#pragma omp tile sizes(4)
for (int i = 0; i < 6; ++i)
for (int j = 0; j < n; ++j)
body(i + j);
}
//.
// IR: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
// IR: [[META3]] = !{!"llvm.loop.mustprogress"}
// IR: [[LOOP4]] = distinct !{[[LOOP4]], [[META3]]}
// IR: [[LOOP5]] = distinct !{[[LOOP5]], [[META3]]}
// IR: [[LOOP6]] = distinct !{[[LOOP6]], [[META3]]}
// IR: [[LOOP7]] = distinct !{[[LOOP7]], [[META3]]}
//.