Since C++11, the C++ standard has a forward progress guarantee [intro.progress], so all such functions must have the `mustprogress` requirement. In addition, from C11 and onwards, loops without a non-zero constant conditional or no conditional are also required to make progress (C11 6.8.5p6). This patch implements these attribute deductions so they can be used by the optimization passes. Differential Revision: https://reviews.llvm.org/D86841
101 lines
4.1 KiB
Plaintext
101 lines
4.1 KiB
Plaintext
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
|
// Check that the CHECK lines are generated for clang-generated functions
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp %s -emit-llvm -o - | FileCheck --check-prefix=OMP %s
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck --check-prefix=NOOMP %s
|
|
|
|
const int size = 1024 * 1024 * 32;
|
|
|
|
double A[size];
|
|
|
|
void foo(void);
|
|
|
|
// OMP-LABEL: @main(
|
|
// OMP-NEXT: entry:
|
|
// OMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
|
|
// OMP-NEXT: [[I:%.*]] = alloca i32, align 4
|
|
// OMP-NEXT: store i32 0, i32* [[RETVAL]], align 4
|
|
// OMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB2:@.*]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*))
|
|
// OMP-NEXT: call void @foo()
|
|
// OMP-NEXT: ret i32 0
|
|
//
|
|
// NOOMP-LABEL: @main(
|
|
// NOOMP-NEXT: entry:
|
|
// NOOMP-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
|
|
// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4
|
|
// NOOMP-NEXT: store i32 0, i32* [[RETVAL]], align 4
|
|
// NOOMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// NOOMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// NOOMP-NEXT: br label [[FOR_COND:%.*]]
|
|
// NOOMP: for.cond:
|
|
// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432
|
|
// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
|
|
// NOOMP: for.body:
|
|
// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64
|
|
// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]]
|
|
// NOOMP-NEXT: store double 0.000000e+00, double* [[ARRAYIDX]], align 8
|
|
// NOOMP-NEXT: br label [[FOR_INC:%.*]]
|
|
// NOOMP: for.inc:
|
|
// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1
|
|
// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4
|
|
// NOOMP-NEXT: br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]]
|
|
// NOOMP: for.end:
|
|
// NOOMP-NEXT: call void @foo()
|
|
// NOOMP-NEXT: ret i32 0
|
|
//
|
|
int main() {
|
|
int i = 0;
|
|
|
|
#pragma omp parallel for
|
|
for (i = 0; i < size; ++i) {
|
|
A[i] = 0.0;
|
|
}
|
|
|
|
foo();
|
|
|
|
return 0;
|
|
}
|
|
|
|
// OMP-LABEL: @foo(
|
|
// OMP-NEXT: entry:
|
|
// OMP-NEXT: [[I:%.*]] = alloca i32, align 4
|
|
// OMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// OMP-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB2]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*))
|
|
// OMP-NEXT: ret void
|
|
//
|
|
// NOOMP-LABEL: @foo(
|
|
// NOOMP-NEXT: entry:
|
|
// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4
|
|
// NOOMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// NOOMP-NEXT: store i32 0, i32* [[I]], align 4
|
|
// NOOMP-NEXT: br label [[FOR_COND:%.*]]
|
|
// NOOMP: for.cond:
|
|
// NOOMP-NEXT: [[TMP0:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 33554432
|
|
// NOOMP-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
|
|
// NOOMP: for.body:
|
|
// NOOMP-NEXT: [[TMP1:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64
|
|
// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], [33554432 x double]* @A, i64 0, i64 [[IDXPROM]]
|
|
// NOOMP-NEXT: store double 1.000000e+00, double* [[ARRAYIDX]], align 8
|
|
// NOOMP-NEXT: br label [[FOR_INC:%.*]]
|
|
// NOOMP: for.inc:
|
|
// NOOMP-NEXT: [[TMP2:%.*]] = load i32, i32* [[I]], align 4
|
|
// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1
|
|
// NOOMP-NEXT: store i32 [[INC]], i32* [[I]], align 4
|
|
// NOOMP-NEXT: br label [[FOR_COND]], [[LOOP4:!llvm.loop !.*]]
|
|
// NOOMP: for.end:
|
|
// NOOMP-NEXT: ret void
|
|
//
|
|
void foo(void) {
|
|
int i = 0;
|
|
|
|
#pragma omp parallel for
|
|
for (i = 0; i < size; ++i) {
|
|
A[i] = 1.0;
|
|
}
|
|
}
|