Skip to content

Commit

Permalink
[UTC] Add fallback support for specific metadata, and check their defs
Browse files Browse the repository at this point in the history
This prevents update_cc_tests.py from emitting hard-coded identifiers
for metadata (global variable checkers still check hard-coded
identifiers). Instead it emits regex checkers that match even if the
identifiers change. Also adds a new mode for --check-globals: instead of
simply being on or off, it now has the options 'none', 'smart' and
'all', with 'none' and 'all' corresponding to the previous modes.

The 'smart' mode only emits checks for global definitions referenced
in the IR or other metadata that itself has a definition checker
emitted, making the rule transitive. It does not emit checks for
attribute sets, since that is better checked by --check-attributes. This
mode is made the new default. To make the change in default mode
backwards compatible a version bump is introduced (to v3), and the
default remains 'none' in v1 & v2.

This will result in metadata checks being emitted more often, so filters
are added to not check absolute file paths and compiler version git
hashes.

rdar://105239218
  • Loading branch information
hnrklssn committed Jul 5, 2023
1 parent c6a4fc8 commit 8a3fdf7
Show file tree
Hide file tree
Showing 20 changed files with 1,243 additions and 98 deletions.
6 changes: 6 additions & 0 deletions clang/test/utils/update_cc_test_checks/Inputs/annotations.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s

int foo() {
int x = x + 1;
return x;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s

// CHECK-LABEL: define dso_local i32 @foo
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 0, ptr [[X]], align 4, !annotation [[META2:![0-9]+]]
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1
// CHECK-NEXT: store i32 [[ADD]], ptr [[X]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[X]], align 4
// CHECK-NEXT: ret i32 [[TMP1]]
//
int foo() {
int x = x + 1;
return x;
}
//.
// CHECK: [[META2]] = !{!"auto-init"}
//.
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs
// 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);

int main(void) {
int i = 0;

#pragma omp parallel for
for (i = 0; i < size; ++i) {
A[i] = 0.0;
}

foo();

return 0;
}

void foo(void) {
int i = 0;

#pragma omp parallel for
for (i = 0; i < size; ++i) {
A[i] = 1.0;
}
}
//.
// OMP: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [23 x i8] c"
// OMP: @[[GLOB1:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 514, i32 0, i32 22, ptr @[[GLOB0]] }, align 8
// OMP: @[[GLOB2:[0-9]+]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @[[GLOB0]] }, align 8
//.
// OMP: @A = global [33554432 x double] zeroinitializer, align 16
// OMP: @size = constant i32 33554432, align 4
//.
// NOOMP: @size = constant i32 33554432, align 4
// NOOMP: @A = global [33554432 x double] zeroinitializer, align 16
//.
// 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, ptr [[RETVAL]], align 4
// OMP-NEXT: store i32 0, ptr [[I]], align 4
// OMP-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @main.omp_outlined)
// OMP-NEXT: call void @foo()
// OMP-NEXT: ret i32 0
//
//
// OMP-LABEL: @main.omp_outlined(
// OMP-NEXT: entry:
// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
// OMP-NEXT: [[I:%.*]] = alloca i32, align 4
// OMP-NEXT: store ptr [[DOTGLOBAL_TID_:%.*]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
// OMP-NEXT: store ptr [[DOTBOUND_TID_:%.*]], ptr [[DOTBOUND_TID__ADDR]], align 8
// OMP-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
// OMP-NEXT: store i32 33554431, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4
// OMP-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
// OMP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// OMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
// OMP-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1]], i32 [[TMP1]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
// OMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431
// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
// OMP: cond.true:
// OMP-NEXT: br label [[COND_END:%.*]]
// OMP: cond.false:
// OMP-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: br label [[COND_END]]
// OMP: cond.end:
// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ]
// OMP-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
// OMP-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]]
// OMP: omp.inner.for.cond:
// OMP-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]]
// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]]
// OMP: omp.inner.for.body:
// OMP-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1
// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]]
// OMP-NEXT: store i32 [[ADD]], ptr [[I]], align 4
// OMP-NEXT: [[TMP8:%.*]] = load i32, ptr [[I]], align 4
// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64
// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]]
// OMP-NEXT: store double 0.000000e+00, ptr [[ARRAYIDX]], align 8
// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]]
// OMP: omp.body.continue:
// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]]
// OMP: omp.inner.for.inc:
// OMP-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1
// OMP-NEXT: store i32 [[ADD2]], ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: br label [[OMP_INNER_FOR_COND]]
// OMP: omp.inner.for.end:
// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// OMP: omp.loop.exit:
// OMP-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
// OMP-NEXT: ret void
//
//
// OMP-LABEL: @foo(
// OMP-NEXT: entry:
// OMP-NEXT: [[I:%.*]] = alloca i32, align 4
// OMP-NEXT: store i32 0, ptr [[I]], align 4
// OMP-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @foo.omp_outlined)
// OMP-NEXT: ret void
//
//
// OMP-LABEL: @foo.omp_outlined(
// OMP-NEXT: entry:
// OMP-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
// OMP-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
// OMP-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
// OMP-NEXT: [[TMP:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
// OMP-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
// OMP-NEXT: [[I:%.*]] = alloca i32, align 4
// OMP-NEXT: store ptr [[DOTGLOBAL_TID_:%.*]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
// OMP-NEXT: store ptr [[DOTBOUND_TID_:%.*]], ptr [[DOTBOUND_TID__ADDR]], align 8
// OMP-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
// OMP-NEXT: store i32 33554431, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4
// OMP-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
// OMP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// OMP-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
// OMP-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1]], i32 [[TMP1]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
// OMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], 33554431
// OMP-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
// OMP: cond.true:
// OMP-NEXT: br label [[COND_END:%.*]]
// OMP: cond.false:
// OMP-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: br label [[COND_END]]
// OMP: cond.end:
// OMP-NEXT: [[COND:%.*]] = phi i32 [ 33554431, [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ]
// OMP-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
// OMP-NEXT: store i32 [[TMP4]], ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: br label [[OMP_INNER_FOR_COND:%.*]]
// OMP: omp.inner.for.cond:
// OMP-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
// OMP-NEXT: [[CMP1:%.*]] = icmp sle i32 [[TMP5]], [[TMP6]]
// OMP-NEXT: br i1 [[CMP1]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]]
// OMP: omp.inner.for.body:
// OMP-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], 1
// OMP-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]]
// OMP-NEXT: store i32 [[ADD]], ptr [[I]], align 4
// OMP-NEXT: [[TMP8:%.*]] = load i32, ptr [[I]], align 4
// OMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP8]] to i64
// OMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]]
// OMP-NEXT: store double 1.000000e+00, ptr [[ARRAYIDX]], align 8
// OMP-NEXT: br label [[OMP_BODY_CONTINUE:%.*]]
// OMP: omp.body.continue:
// OMP-NEXT: br label [[OMP_INNER_FOR_INC:%.*]]
// OMP: omp.inner.for.inc:
// OMP-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP9]], 1
// OMP-NEXT: store i32 [[ADD2]], ptr [[DOTOMP_IV]], align 4
// OMP-NEXT: br label [[OMP_INNER_FOR_COND]]
// OMP: omp.inner.for.end:
// OMP-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// OMP: omp.loop.exit:
// OMP-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
// OMP-NEXT: ret void
//
//
// 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, ptr [[RETVAL]], align 4
// NOOMP-NEXT: store i32 0, ptr [[I]], align 4
// NOOMP-NEXT: store i32 0, ptr [[I]], align 4
// NOOMP-NEXT: br label [[FOR_COND:%.*]]
// NOOMP: for.cond:
// NOOMP-NEXT: [[TMP0:%.*]] = load i32, ptr [[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, ptr [[I]], align 4
// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64
// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]]
// NOOMP-NEXT: store double 0.000000e+00, ptr [[ARRAYIDX]], align 8
// NOOMP-NEXT: br label [[FOR_INC:%.*]]
// NOOMP: for.inc:
// NOOMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4
// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1
// NOOMP-NEXT: store i32 [[INC]], ptr [[I]], align 4
// NOOMP-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP2:![0-9]+]]
// NOOMP: for.end:
// NOOMP-NEXT: call void @foo()
// NOOMP-NEXT: ret i32 0
//
//
// NOOMP-LABEL: @foo(
// NOOMP-NEXT: entry:
// NOOMP-NEXT: [[I:%.*]] = alloca i32, align 4
// NOOMP-NEXT: store i32 0, ptr [[I]], align 4
// NOOMP-NEXT: store i32 0, ptr [[I]], align 4
// NOOMP-NEXT: br label [[FOR_COND:%.*]]
// NOOMP: for.cond:
// NOOMP-NEXT: [[TMP0:%.*]] = load i32, ptr [[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, ptr [[I]], align 4
// NOOMP-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP1]] to i64
// NOOMP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [33554432 x double], ptr @A, i64 0, i64 [[IDXPROM]]
// NOOMP-NEXT: store double 1.000000e+00, ptr [[ARRAYIDX]], align 8
// NOOMP-NEXT: br label [[FOR_INC:%.*]]
// NOOMP: for.inc:
// NOOMP-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4
// NOOMP-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1
// NOOMP-NEXT: store i32 [[INC]], ptr [[I]], align 4
// NOOMP-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]]
// NOOMP: for.end:
// NOOMP-NEXT: ret void
//
//.
// OMP: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// OMP: attributes #[[ATTR1:[0-9]+]] = { noinline norecurse nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// OMP: attributes #[[ATTR2:[0-9]+]] = { nounwind }
//.
// NOOMP: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
//.
// OMP: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// OMP: [[META1:![0-9]+]] = !{i32 7, !"openmp", i32 51}
// OMP: [[META2:![0-9]+]] = !{!"clang version {{.*}}"}
// OMP: [[META3:![0-9]+]] = !{[[META4:![0-9]+]]}
// OMP: [[META4]] = !{i64 2, i64 -1, i64 -1, i1 true}
//.
// NOOMP: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// NOOMP: [[META1:![0-9]+]] = !{!"clang version {{.*}}"}
// NOOMP: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
// NOOMP: [[META3]] = !{!"llvm.loop.mustprogress"}
// NOOMP: [[LOOP4]] = distinct !{[[LOOP4]], [[META3]]}
//.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals smart --include-generated-funcs
// 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
Expand Down Expand Up @@ -227,3 +227,8 @@ void foo(void) {
// NOOMP: for.end:
// NOOMP-NEXT: ret void
//
//.
// NOOMP: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
// NOOMP: [[META3]] = !{!"llvm.loop.mustprogress"}
// NOOMP: [[LOOP4]] = distinct !{[[LOOP4]], [[META3]]}
//.

0 comments on commit 8a3fdf7

Please sign in to comment.