mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 11:56:42 +00:00

This PR removes the old `nocapture` attribute, replacing it with the new `captures` attribute introduced in #116990. This change is intended to be essentially NFC, replacing existing uses of `nocapture` with `captures(none)` without adding any new analysis capabilities. Making use of non-`none` values is left for a followup. Some notes: * `nocapture` will be upgraded to `captures(none)` by the bitcode reader. * `nocapture` will also be upgraded by the textual IR reader. This is to make it easier to use old IR files and somewhat reduce the test churn in this PR. * Helper APIs like `doesNotCapture()` will check for `captures(none)`. * MLIR import will convert `captures(none)` into an `llvm.nocapture` attribute. The representation in the LLVM IR dialect should be updated separately.
182 lines
7.0 KiB
C++
182 lines
7.0 KiB
C++
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
|
|
// REQUIRES: webassembly-registered-target
|
|
|
|
// Simple calls to known variadic functions that are completely elided when
|
|
// optimisations are on This is a functional check that the expand-variadic pass
|
|
// is consistent with clang's va_arg handling
|
|
|
|
// When expand-variadics is added to the default pipeline, clang -O1 will
|
|
// suffice here -Wno-varargs avoids warning second argument to 'va_start' is not
|
|
// the last named parameter
|
|
|
|
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -Wno-varargs -O1 -emit-llvm -o - | opt - -S --passes='module(expand-variadics,default<O1>)' --expand-variadics-override=optimize -o - | FileCheck %s
|
|
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
|
|
template <typename X, typename Y> static X first(...) {
|
|
va_list va;
|
|
__builtin_va_start(va, 0);
|
|
X r = va_arg(va, X);
|
|
va_end(va);
|
|
return r;
|
|
}
|
|
|
|
template <typename X, typename Y> static Y second(...) {
|
|
va_list va;
|
|
__builtin_va_start(va, 0);
|
|
va_arg(va, X);
|
|
Y r = va_arg(va, Y);
|
|
va_end(va);
|
|
return r;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_pair_i32
|
|
// CHECK-SAME: (i32 noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[X]]
|
|
//
|
|
int first_pair_i32(int x, int y) { return first<int, int>(x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_pair_i32
|
|
// CHECK-SAME: (i32 noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[Y]]
|
|
//
|
|
int second_pair_i32(int x, int y) { return second<int, int>(x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_pair_f64
|
|
// CHECK-SAME: (double noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret double [[X]]
|
|
//
|
|
double first_pair_f64(double x, double y) {
|
|
return first<double, double>(x, y);
|
|
}
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_pair_f64
|
|
// CHECK-SAME: (double noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret double [[Y]]
|
|
//
|
|
double second_pair_f64(double x, double y) {
|
|
return second<double, double>(x, y);
|
|
}
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_i32_f64
|
|
// CHECK-SAME: (i32 noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[X]]
|
|
//
|
|
int first_i32_f64(int x, double y) { return first<int, double>(x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_i32_f64
|
|
// CHECK-SAME: (i32 noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret double [[Y]]
|
|
//
|
|
double second_i32_f64(int x, double y) { return second<int, double>(x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_f64_i32
|
|
// CHECK-SAME: (double noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret double [[X]]
|
|
//
|
|
double first_f64_i32(double x, int y) { return first<double, int>(x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_f64_i32
|
|
// CHECK-SAME: (double noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[Y]]
|
|
//
|
|
int second_f64_i32(double x, int y) { return second<double, int>(x, y); }
|
|
}
|
|
|
|
extern "C" {
|
|
typedef uint64_t ulong2 __attribute__((__vector_size__(16), __aligned__(16)));
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_i32_ulong2
|
|
// CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[X]]
|
|
//
|
|
int first_i32_ulong2(int x, ulong2 *y) { return first<int, ulong2>(x, *y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_i32_ulong2
|
|
// CHECK-SAME: (i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[TBAA2:![0-9]+]]
|
|
// CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
void second_i32_ulong2(int x, ulong2 *y, ulong2 *r) {
|
|
*r = second<int, ulong2>(x, *y);
|
|
}
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_ulong2_i32
|
|
// CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[TBAA2]]
|
|
// CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
void first_ulong2_i32(ulong2 *x, int y, ulong2 *r) {
|
|
*r = first<ulong2, int>(*x, y);
|
|
}
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_ulong2_i32
|
|
// CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[Y]]
|
|
//
|
|
int second_ulong2_i32(ulong2 *x, int y) { return second<ulong2, int>(*x, y); }
|
|
}
|
|
|
|
// ascending alignment
|
|
typedef struct {
|
|
char c;
|
|
short s;
|
|
int i;
|
|
long l;
|
|
float f;
|
|
double d;
|
|
} asc;
|
|
|
|
extern "C" {
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_i32_asc
|
|
// CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[X]]
|
|
//
|
|
int first_i32_asc(int x, asc *y) { return first<int, asc>(x, *y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_i32_asc
|
|
// CHECK-SAME: (i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[Y]], i32 24, i1 false)
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
void second_i32_asc(int x, asc *y, asc *r) { *r = second<int, asc>(x, *y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@first_asc_i32
|
|
// CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[X]], i32 24, i1 false)
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
void first_asc_i32(asc *x, int y, asc *r) { *r = first<asc, int>(*x, y); }
|
|
|
|
// CHECK-LABEL: define {{[^@]+}}@second_asc_i32
|
|
// CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: ret i32 [[Y]]
|
|
//
|
|
int second_asc_i32(asc *x, int y) { return second<asc, int>(*x, y); }
|
|
}
|