| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,248 @@ | ||
| /* ===--- amxtransposeintrin.h - AMX_TRANSPOSE intrinsics -*- C++ -*---------=== | ||
| * | ||
| * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| * See https://llvm.org/LICENSE.txt for license information. | ||
| * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| * | ||
| * ===-----------------------------------------------------------------------=== | ||
| */ | ||
|
|
||
| #ifndef __IMMINTRIN_H | ||
| #error "Never use <amxtransposeintrin.h> directly; use <immintrin.h> instead." | ||
| #endif /* __IMMINTRIN_H */ | ||
|
|
||
| #ifndef __AMX_TRANSPOSEINTRIN_H | ||
| #define __AMX_TRANSPOSEINTRIN_H | ||
| #ifdef __x86_64__ | ||
|
|
||
| #define __DEFAULT_FN_ATTRS_TRANSPOSE \ | ||
| __attribute__((__always_inline__, __nodebug__, __target__("amx-transpose"))) | ||
|
|
||
| #define _tile_2rpntlvwz0(tdst, base, stride) \ | ||
| __builtin_ia32_t2rpntlvwz0(tdst, base, stride) | ||
| #define _tile_2rpntlvwz0t1(tdst, base, stride) \ | ||
| __builtin_ia32_t2rpntlvwz0t1(tdst, base, stride) | ||
| #define _tile_2rpntlvwz1(tdst, base, stride) \ | ||
| __builtin_ia32_t2rpntlvwz1(tdst, base, stride) | ||
| #define _tile_2rpntlvwz1t1(tdst, base, stride) \ | ||
| __builtin_ia32_t2rpntlvwz1t1(tdst, base, stride) | ||
|
|
||
| /// Transpose 32-bit elements from \a src and write the result to \a dst. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// \code | ||
| /// void _tile_transposed(__tile dst, __tile src); | ||
| /// \endcode | ||
| /// | ||
| /// This intrinsic corresponds to the <c> TTRANSPOSED </c> instruction. | ||
| /// | ||
| /// \param dst | ||
| /// The destination tile. Max size is 1024 Bytes. | ||
| /// \param src | ||
| /// The source tile. Max size is 1024 Bytes. | ||
| /// | ||
| /// \code{.operation} | ||
| /// | ||
| /// FOR i := 0 TO (dst.rows-1) | ||
| /// tmp[511:0] := 0 | ||
| /// FOR j := 0 TO (dst.colsb/4-1) | ||
| /// tmp.dword[j] := src.row[j].dword[i] | ||
| /// ENDFOR | ||
| /// dst.row[i] := tmp | ||
| /// ENDFOR | ||
| /// | ||
| /// zero_upper_rows(dst, dst.rows) | ||
| /// zero_tileconfig_start() | ||
| /// \endcode | ||
| #define _tile_transposed(dst, src) __builtin_ia32_ttransposed(dst, src) | ||
|
|
||
| static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz0_internal( | ||
| unsigned short row, unsigned short col0, unsigned short col1, | ||
| _tile1024i *dst0, _tile1024i *dst1, const void *base, | ||
| __SIZE_TYPE__ stride) { | ||
| // Use __tile1024i_1024a* to escape the alignment check in | ||
| // clang/test/Headers/x86-intrinsics-headers-clean.cpp | ||
| __builtin_ia32_t2rpntlvwz0_internal(row, col0, col1, (_tile1024i_1024a *)dst0, | ||
| (_tile1024i_1024a *)dst1, base, | ||
| (__SIZE_TYPE__)(stride)); | ||
| } | ||
|
|
||
| static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz0t1_internal( | ||
| unsigned short row, unsigned short col0, unsigned short col1, | ||
| _tile1024i *dst0, _tile1024i *dst1, const void *base, | ||
| __SIZE_TYPE__ stride) { | ||
| __builtin_ia32_t2rpntlvwz0t1_internal( | ||
| row, col0, col1, (_tile1024i_1024a *)dst0, (_tile1024i_1024a *)dst1, base, | ||
| (__SIZE_TYPE__)(stride)); | ||
| } | ||
|
|
||
| static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz1_internal( | ||
| unsigned short row, unsigned short col0, unsigned short col1, | ||
| _tile1024i *dst0, _tile1024i *dst1, const void *base, | ||
| __SIZE_TYPE__ stride) { | ||
| __builtin_ia32_t2rpntlvwz1_internal(row, col0, col1, (_tile1024i_1024a *)dst0, | ||
| (_tile1024i_1024a *)dst1, base, | ||
| (__SIZE_TYPE__)(stride)); | ||
| } | ||
|
|
||
| static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz1t1_internal( | ||
| unsigned short row, unsigned short col0, unsigned short col1, | ||
| _tile1024i *dst0, _tile1024i *dst1, const void *base, | ||
| __SIZE_TYPE__ stride) { | ||
| __builtin_ia32_t2rpntlvwz1t1_internal( | ||
| row, col0, col1, (_tile1024i_1024a *)dst0, (_tile1024i_1024a *)dst1, base, | ||
| (__SIZE_TYPE__)(stride)); | ||
| } | ||
|
|
||
| // This is internal intrinsic. C/C++ user should avoid calling it directly. | ||
| static __inline__ _tile1024i __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| _tile_transposed_internal(unsigned short m, unsigned short n, _tile1024i src) { | ||
| return __builtin_ia32_ttransposed_internal(m, n, src); | ||
| } | ||
|
|
||
| /// Converts a pair of tiles from memory into VNNI format, and places the | ||
| /// results in a pair of destinations specified by dst. The pair of tiles | ||
| /// in memory is specified via a tsib; the second tile is after the first | ||
| /// one, separated by the same stride that separates each row. | ||
| /// The tile configuration for the destination tiles indicates the amount | ||
| /// of data to read from memory. The instruction will load a number of rows | ||
| /// that is equal to twice the number of rows in tmm1. The size of each row | ||
| /// is equal to the average width of the destination tiles. If the second | ||
| /// tile is configured with zero rows and columns, only the first tile will | ||
| /// be written. | ||
| /// Provides a hint to the implementation that the data will likely not be | ||
| /// reused in the near future and the data caching can be optimized. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// This intrinsic corresponds to the <c> T2RPNTLVWZ0 </c> instruction. | ||
| /// | ||
| /// \param dst0 | ||
| /// First tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param dst1 | ||
| /// Second tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param base | ||
| /// A pointer to base address. | ||
| /// \param stride | ||
| /// The stride between the rows' data to be loaded in memory. | ||
| __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| static void __tile_2rpntlvwz0(__tile1024i *dst0, __tile1024i *dst1, | ||
| const void *base, __SIZE_TYPE__ stride) { | ||
| _tile_2rpntlvwz0_internal(dst0->row, dst0->col, dst1->col, &dst0->tile, | ||
| &dst1->tile, base, stride); | ||
| } | ||
|
|
||
| /// Converts a pair of tiles from memory into VNNI format, and places the | ||
| /// results in a pair of destinations specified by dst. The pair of tiles | ||
| /// in memory is specified via a tsib; the second tile is after the first | ||
| /// one, separated by the same stride that separates each row. | ||
| /// The tile configuration for the destination tiles indicates the amount | ||
| /// of data to read from memory. The instruction will load a number of rows | ||
| /// that is equal to twice the number of rows in tmm1. The size of each row | ||
| /// is equal to the average width of the destination tiles. If the second | ||
| /// tile is configured with zero rows and columns, only the first tile will | ||
| /// be written. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// This intrinsic corresponds to the <c> T2RPNTLVWZ0T1 </c> instruction. | ||
| /// | ||
| /// \param dst0 | ||
| /// First tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param dst1 | ||
| /// Second tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param base | ||
| /// A pointer to base address. | ||
| /// \param stride | ||
| /// The stride between the rows' data to be loaded in memory. | ||
| __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| static void __tile_2rpntlvwz0t1(__tile1024i *dst0, __tile1024i *dst1, | ||
| const void *base, __SIZE_TYPE__ stride) { | ||
| _tile_2rpntlvwz0t1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile, | ||
| &dst1->tile, base, stride); | ||
| } | ||
|
|
||
| /// Converts a pair of tiles from memory into VNNI format, and places the | ||
| /// results in a pair of destinations specified by dst. The pair of tiles | ||
| /// in memory is specified via a tsib; the second tile is after the first | ||
| /// one, separated by the same stride that separates each row. | ||
| /// The tile configuration for the destination tiles indicates the amount | ||
| /// of data to read from memory. The instruction will load a number of rows | ||
| /// that is equal to twice the number of rows in tmm1. The size of each row | ||
| /// is equal to the average width of the destination tiles. If the second | ||
| /// tile is configured with zero rows and columns, only the first tile will | ||
| /// be written. The last row will be not be read from memory but instead | ||
| /// filled with zeros. | ||
| /// Provides a hint to the implementation that the data will likely not be | ||
| /// reused in the near future and the data caching can be optimized. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// This intrinsic corresponds to the <c> T2RPNTLVWZ1 </c> instruction. | ||
| /// | ||
| /// \param dst0 | ||
| /// First tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param dst1 | ||
| /// Second tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param base | ||
| /// A pointer to base address. | ||
| /// \param stride | ||
| /// The stride between the rows' data to be loaded in memory. | ||
| __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| static void __tile_2rpntlvwz1(__tile1024i *dst0, __tile1024i *dst1, | ||
| const void *base, __SIZE_TYPE__ stride) { | ||
| _tile_2rpntlvwz1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile, | ||
| &dst1->tile, base, stride); | ||
| } | ||
|
|
||
| /// Converts a pair of tiles from memory into VNNI format, and places the | ||
| /// results in a pair of destinations specified by dst. The pair of tiles | ||
| /// in memory is specified via a tsib; the second tile is after the first | ||
| /// one, separated by the same stride that separates each row. | ||
| /// The tile configuration for the destination tiles indicates the amount | ||
| /// of data to read from memory. The instruction will load a number of rows | ||
| /// that is equal to twice the number of rows in tmm1. The size of each row | ||
| /// is equal to the average width of the destination tiles. If the second | ||
| /// tile is configured with zero rows and columns, only the first tile will | ||
| /// be written. The last row will be not be read from memory but instead | ||
| /// filled with zeros. | ||
| /// Provides a hint to the implementation that the data will likely not be | ||
| /// reused in the near future and the data caching can be optimized. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// This intrinsic corresponds to the <c> T2RPNTLVWZ1T1 </c> instruction. | ||
| /// | ||
| /// \param dst0 | ||
| /// First tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param dst1 | ||
| /// Second tile of destination tile pair. Max size is 1024i*2 Bytes. | ||
| /// \param base | ||
| /// A pointer to base address. | ||
| /// \param stride | ||
| /// The stride between the rows' data to be loaded in memory. | ||
| __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| static void __tile_2rpntlvwz1t1(__tile1024i *dst0, __tile1024i *dst1, | ||
| const void *base, __SIZE_TYPE__ stride) { | ||
| _tile_2rpntlvwz1t1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile, | ||
| &dst1->tile, base, stride); | ||
| } | ||
|
|
||
| /// Transpose 32-bit elements from src and write the result to dst. | ||
| /// | ||
| /// \headerfile <immintrin.h> | ||
| /// | ||
| /// This intrinsic corresponds to the <c> TTRANSPOSED </c> instruction. | ||
| /// | ||
| /// \param dst | ||
| /// The destination tile. Max size is 1024 Bytes. | ||
| /// \param src | ||
| /// The source tile. Max size is 1024 Bytes. | ||
| __DEFAULT_FN_ATTRS_TRANSPOSE | ||
| static void __tile_transposed(__tile1024i *dst, __tile1024i src) { | ||
| dst->tile = _tile_transposed_internal(dst->row, dst->col, src.tile); | ||
| } | ||
|
|
||
| #endif /* __x86_64__ */ | ||
| #endif /* __AMX_TRANSPOSEINTRIN_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s | ||
| // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char | ||
| // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s | ||
|
|
||
| // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter | ||
| // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter | ||
| // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter | ||
|
|
||
| // both-no-diagnostics | ||
|
|
||
| typedef decltype(nullptr) nullptr_t; | ||
| typedef __INTPTR_TYPE__ intptr_t; | ||
|
|
||
| static_assert(sizeof(int) == 4); | ||
| static_assert(sizeof(long long) == 8); | ||
|
|
||
| template <class To, class From> | ||
| constexpr To bit_cast(const From &from) { | ||
| static_assert(sizeof(To) == sizeof(From)); | ||
| return __builtin_bit_cast(To, from); | ||
| } | ||
|
|
||
| template <class Intermediate, class Init> | ||
| constexpr bool check_round_trip(const Init &init) { | ||
| return bit_cast<Init>(bit_cast<Intermediate>(init)) == init; | ||
| } | ||
|
|
||
| template <class Intermediate, class Init> | ||
| constexpr Init round_trip(const Init &init) { | ||
| return bit_cast<Init>(bit_cast<Intermediate>(init)); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| namespace test_long_double { | ||
| #if __x86_64 | ||
| #if 0 | ||
| constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\ | ||
| // expected-note{{in call}} | ||
| #endif | ||
| constexpr long double ld = 3.1425926539; | ||
|
|
||
| struct bytes { | ||
| unsigned char d[16]; | ||
| }; | ||
|
|
||
| // static_assert(round_trip<bytes>(ld), ""); | ||
|
|
||
| static_assert(round_trip<long double>(10.0L)); | ||
|
|
||
| #if 0 | ||
| constexpr bool f(bool read_uninit) { | ||
| bytes b = bit_cast<bytes>(ld); | ||
| unsigned char ld_bytes[10] = { | ||
| 0x0, 0x48, 0x9f, 0x49, 0xf0, | ||
| 0x3c, 0x20, 0xc9, 0x0, 0x40, | ||
| }; | ||
|
|
||
| for (int i = 0; i != 10; ++i) | ||
| if (ld_bytes[i] != b.d[i]) | ||
| return false; | ||
|
|
||
| if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}} | ||
| return false; | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| static_assert(f(/*read_uninit=*/false), ""); | ||
| static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \ | ||
| // expected-note{{in call to 'f(true)'}} | ||
| #endif | ||
| constexpr bytes ld539 = { | ||
| 0x0, 0x0, 0x0, 0x0, | ||
| 0x0, 0x0, 0xc0, 0x86, | ||
| 0x8, 0x40, 0x0, 0x0, | ||
| 0x0, 0x0, 0x0, 0x0, | ||
| }; | ||
|
|
||
| constexpr long double fivehundredandthirtynine = 539.0; | ||
|
|
||
| static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, ""); | ||
| #else | ||
| static_assert(round_trip<__int128_t>(34.0L)); | ||
| #endif | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,342 @@ | ||
| // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedLocalVarsChecker -verify %s | ||
|
|
||
| #include "mock-types.h" | ||
| #include "mock-system-header.h" | ||
|
|
||
| void someFunction(); | ||
|
|
||
| namespace raw_ptr { | ||
| void foo() { | ||
| CheckedObj *bar; | ||
| // FIXME: later on we might warn on uninitialized vars too | ||
| } | ||
|
|
||
| void bar(CheckedObj *) {} | ||
| } // namespace raw_ptr | ||
|
|
||
| namespace reference { | ||
| void foo_ref() { | ||
| CheckedObj automatic; | ||
| CheckedObj &bar = automatic; | ||
| // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| someFunction(); | ||
| bar.method(); | ||
| } | ||
|
|
||
| void foo_ref_trivial() { | ||
| CheckedObj automatic; | ||
| CheckedObj &bar = automatic; | ||
| } | ||
|
|
||
| void bar_ref(CheckedObj &) {} | ||
| } // namespace reference | ||
|
|
||
| namespace guardian_scopes { | ||
| void foo1() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| { CheckedObj *bar = foo.get(); } | ||
| } | ||
|
|
||
| void foo2() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| // missing embedded scope here | ||
| CheckedObj *bar = foo.get(); | ||
| // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| someFunction(); | ||
| bar->method(); | ||
| } | ||
|
|
||
| void foo3() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| { | ||
| { CheckedObj *bar = foo.get(); } | ||
| } | ||
| } | ||
|
|
||
| void foo4() { | ||
| { | ||
| CheckedPtr<CheckedObj> foo; | ||
| { CheckedObj *bar = foo.get(); } | ||
| } | ||
| } | ||
|
|
||
| void foo5() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| auto* bar = foo.get(); | ||
| bar->trivial(); | ||
| } | ||
|
|
||
| void foo6() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| auto* bar = foo.get(); | ||
| // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| bar->method(); | ||
| } | ||
|
|
||
| struct SelfReferencingStruct { | ||
| SelfReferencingStruct* ptr; | ||
| CheckedObj* obj { nullptr }; | ||
| }; | ||
|
|
||
| void foo7(CheckedObj* obj) { | ||
| SelfReferencingStruct bar = { &bar, obj }; | ||
| bar.obj->method(); | ||
| } | ||
|
|
||
| } // namespace guardian_scopes | ||
|
|
||
| namespace auto_keyword { | ||
| class Foo { | ||
| CheckedObj *provide_ref_ctnbl(); | ||
|
|
||
| void evil_func() { | ||
| CheckedObj *bar = provide_ref_ctnbl(); | ||
| // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| auto *baz = provide_ref_ctnbl(); | ||
| // expected-warning@-1{{Local variable 'baz' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| auto *baz2 = this->provide_ref_ctnbl(); | ||
| // expected-warning@-1{{Local variable 'baz2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| [[clang::suppress]] auto *baz_suppressed = provide_ref_ctnbl(); // no-warning | ||
| } | ||
|
|
||
| void func() { | ||
| CheckedObj *bar = provide_ref_ctnbl(); | ||
| // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| if (bar) | ||
| bar->method(); | ||
| } | ||
| }; | ||
| } // namespace auto_keyword | ||
|
|
||
| namespace guardian_casts { | ||
| void foo1() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| { | ||
| CheckedObj *bar = downcast<CheckedObj>(foo.get()); | ||
| bar->method(); | ||
| } | ||
| foo->method(); | ||
| } | ||
|
|
||
| void foo2() { | ||
| CheckedPtr<CheckedObj> foo; | ||
| { | ||
| CheckedObj *bar = | ||
| static_cast<CheckedObj *>(downcast<CheckedObj>(foo.get())); | ||
| someFunction(); | ||
| } | ||
| } | ||
| } // namespace guardian_casts | ||
|
|
||
| namespace guardian_ref_conversion_operator { | ||
| void foo() { | ||
| CheckedRef<CheckedObj> rc; | ||
| { | ||
| CheckedObj &rr = rc; | ||
| rr.method(); | ||
| someFunction(); | ||
| } | ||
| } | ||
| } // namespace guardian_ref_conversion_operator | ||
|
|
||
| namespace ignore_for_if { | ||
| CheckedObj *provide_ref_ctnbl() { return nullptr; } | ||
|
|
||
| void foo() { | ||
| // no warnings | ||
| if (CheckedObj *a = provide_ref_ctnbl()) | ||
| a->trivial(); | ||
| for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;) | ||
| b->trivial(); | ||
| CheckedObj *array[1]; | ||
| for (CheckedObj *c : array) | ||
| c->trivial(); | ||
| while (CheckedObj *d = provide_ref_ctnbl()) | ||
| d->trivial(); | ||
| do { | ||
| CheckedObj *e = provide_ref_ctnbl(); | ||
| e->trivial(); | ||
| } while (1); | ||
| someFunction(); | ||
| } | ||
|
|
||
| void bar() { | ||
| if (CheckedObj *a = provide_ref_ctnbl()) { | ||
| // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| a->method(); | ||
| } | ||
| for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;) { | ||
| // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| b->method(); | ||
| } | ||
| CheckedObj *array[1]; | ||
| for (CheckedObj *c : array) { | ||
| // expected-warning@-1{{Local variable 'c' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| c->method(); | ||
| } | ||
|
|
||
| while (CheckedObj *d = provide_ref_ctnbl()) { | ||
| // expected-warning@-1{{Local variable 'd' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| d->method(); | ||
| } | ||
| do { | ||
| CheckedObj *e = provide_ref_ctnbl(); | ||
| // expected-warning@-1{{Local variable 'e' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| e->method(); | ||
| } while (1); | ||
| someFunction(); | ||
| } | ||
|
|
||
| } // namespace ignore_for_if | ||
|
|
||
| namespace ignore_system_headers { | ||
|
|
||
| CheckedObj *provide_checkable(); | ||
|
|
||
| void system_header() { | ||
| localVar<CheckedObj>(provide_checkable); | ||
| } | ||
|
|
||
| } // ignore_system_headers | ||
|
|
||
| namespace conditional_op { | ||
| CheckedObj *provide_checkable(); | ||
| bool bar(); | ||
|
|
||
| void foo() { | ||
| CheckedObj *a = bar() ? nullptr : provide_checkable(); | ||
| // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| CheckedPtr<CheckedObj> b = provide_checkable(); | ||
| { | ||
| CheckedObj* c = bar() ? nullptr : b.get(); | ||
| c->method(); | ||
| CheckedObj* d = bar() ? b.get() : nullptr; | ||
| d->method(); | ||
| } | ||
| } | ||
|
|
||
| } // namespace conditional_op | ||
|
|
||
| namespace local_assignment_basic { | ||
|
|
||
| CheckedObj *provide_checkable(); | ||
|
|
||
| void foo(CheckedObj* a) { | ||
| CheckedObj* b = a; | ||
| // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| if (b->trivial()) | ||
| b = provide_checkable(); | ||
| } | ||
|
|
||
| void bar(CheckedObj* a) { | ||
| CheckedObj* b; | ||
| // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| b = provide_checkable(); | ||
| } | ||
|
|
||
| void baz() { | ||
| CheckedPtr a = provide_checkable(); | ||
| { | ||
| CheckedObj* b = a.get(); | ||
| // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| b = provide_checkable(); | ||
| } | ||
| } | ||
|
|
||
| } // namespace local_assignment_basic | ||
|
|
||
| namespace local_assignment_to_parameter { | ||
|
|
||
| CheckedObj *provide_checkable(); | ||
| void someFunction(); | ||
|
|
||
| void foo(CheckedObj* a) { | ||
| a = provide_checkable(); | ||
| // expected-warning@-1{{Assignment to an unchecked parameter 'a' is unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| someFunction(); | ||
| a->method(); | ||
| } | ||
|
|
||
| } // namespace local_assignment_to_parameter | ||
|
|
||
| namespace local_assignment_to_static_local { | ||
|
|
||
| CheckedObj *provide_checkable(); | ||
| void someFunction(); | ||
|
|
||
| void foo() { | ||
| static CheckedObj* a = nullptr; | ||
| // expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| a = provide_checkable(); | ||
| someFunction(); | ||
| a->method(); | ||
| } | ||
|
|
||
| } // namespace local_assignment_to_static_local | ||
|
|
||
| namespace local_assignment_to_global { | ||
|
|
||
| CheckedObj *provide_ref_cntbl(); | ||
| void someFunction(); | ||
|
|
||
| CheckedObj* g_a = nullptr; | ||
| // expected-warning@-1{{Global variable 'local_assignment_to_global::g_a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
|
|
||
| void foo() { | ||
| g_a = provide_ref_cntbl(); | ||
| someFunction(); | ||
| g_a->method(); | ||
| } | ||
|
|
||
| } // namespace local_assignment_to_global | ||
|
|
||
| namespace local_refcountable_checkable_object { | ||
|
|
||
| RefCountableAndCheckable* provide_obj(); | ||
|
|
||
| void local_raw_ptr() { | ||
| RefCountableAndCheckable* a = nullptr; | ||
| // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| a = provide_obj(); | ||
| a->method(); | ||
| } | ||
|
|
||
| void local_checked_ptr() { | ||
| RefPtr<RefCountableAndCheckable> a = nullptr; | ||
| a = provide_obj(); | ||
| a->method(); | ||
| } | ||
|
|
||
| void local_var_with_guardian_checked_ptr() { | ||
| RefPtr<RefCountableAndCheckable> a = provide_obj(); | ||
| { | ||
| auto* b = a.get(); | ||
| b->method(); | ||
| } | ||
| } | ||
|
|
||
| void local_var_with_guardian_checked_ptr_with_assignment() { | ||
| RefPtr<RefCountableAndCheckable> a = provide_obj(); | ||
| { | ||
| RefCountableAndCheckable* b = a.get(); | ||
| // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| b = provide_obj(); | ||
| b->method(); | ||
| } | ||
| } | ||
|
|
||
| void local_var_with_guardian_checked_ref() { | ||
| Ref<RefCountableAndCheckable> a = *provide_obj(); | ||
| { | ||
| RefCountableAndCheckable& b = a; | ||
| b.method(); | ||
| } | ||
| } | ||
|
|
||
| void static_var() { | ||
| static RefCountableAndCheckable* a = nullptr; | ||
| // expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} | ||
| a = provide_obj(); | ||
| } | ||
|
|
||
| } // namespace local_refcountable_checkable_object |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +amx-transpose \ | ||
| // RUN: -target-feature +avx512f -emit-llvm -o - -Wall -Werror -pedantic -Wno-gnu-statement-expression| FileCheck %s | ||
|
|
||
| #include <immintrin.h> | ||
| #include <stddef.h> | ||
|
|
||
| void test_tile_2rpntlvwz0(const void *A, size_t B) { | ||
| // CHECK-LABEL: @test_tile_2rpntlvwz0 | ||
| // CHECK: call void @llvm.x86.t2rpntlvwz0(i8 1, ptr %{{.*}}, i64 %{{.*}}) | ||
| _tile_2rpntlvwz0(1, A, B); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz0t1(const void *A, size_t B) { | ||
| // CHECK-LABEL: @test_tile_2rpntlvwz0t1 | ||
| // CHECK: call void @llvm.x86.t2rpntlvwz0t1(i8 1, ptr %{{.*}}, i64 %{{.*}}) | ||
| _tile_2rpntlvwz0t1(1, A, B); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1(const void *A, size_t B) { | ||
| // CHECK-LABEL: @test_tile_2rpntlvwz1 | ||
| // CHECK: call void @llvm.x86.t2rpntlvwz1(i8 1, ptr %{{.*}}, i64 %{{.*}}) | ||
| _tile_2rpntlvwz1(1, A, B); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1t1(const void *A, size_t B) { | ||
| // CHECK-LABEL: @test_tile_2rpntlvwz1t1 | ||
| // CHECK: call void @llvm.x86.t2rpntlvwz1t1(i8 1, ptr %{{.*}}, i64 %{{.*}}) | ||
| _tile_2rpntlvwz1t1(1, A, B); | ||
| } | ||
|
|
||
| void test_tile_transposed(void) | ||
| { | ||
| // CHECK-LABEL: @test_tile_transposed | ||
| // CHECK: call void @llvm.x86.ttransposed(i8 1, i8 2) | ||
| _tile_transposed(1, 2); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // RUN: %clang_cc1 %s -flax-vector-conversions=none -ffreestanding -triple=x86_64-unknown-unknown -target-feature +avx512f \ | ||
| // RUN: -target-feature +amx-transpose \ | ||
| // RUN: -emit-llvm -o - -Werror -pedantic | FileCheck %s --check-prefixes=CHECK | ||
|
|
||
| #include <immintrin.h> | ||
|
|
||
| char buf[2048]; | ||
| #define STRIDE 32 | ||
|
|
||
| char buf2[2048]; | ||
|
|
||
| void test_tile_2rpntlvwz0(__tile1024i dst0, __tile1024i dst1) { | ||
| //CHECK-LABEL: @test_tile_2rpntlvwz0 | ||
| //CHECK: call { x86_amx, x86_amx } @llvm.x86.t2rpntlvwz0.internal | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 0 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 1 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| __tile_2rpntlvwz0(&dst0, &dst1, buf, STRIDE); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz0t1(__tile1024i dst0, __tile1024i dst1) { | ||
| //CHECK-LABEL: @test_tile_2rpntlvwz0t1 | ||
| //CHECK: call { x86_amx, x86_amx } @llvm.x86.t2rpntlvwz0t1.internal | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 0 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 1 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| __tile_2rpntlvwz0t1(&dst0, &dst1, buf, STRIDE); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1(__tile1024i dst0, __tile1024i dst1) { | ||
| //CHECK-LABEL: @test_tile_2rpntlvwz1 | ||
| //CHECK: call { x86_amx, x86_amx } @llvm.x86.t2rpntlvwz1.internal | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 0 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 1 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| __tile_2rpntlvwz1(&dst0, &dst1, buf, STRIDE); | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1t1(__tile1024i dst0, __tile1024i dst1) { | ||
| //CHECK-LABEL: @test_tile_2rpntlvwz1t1 | ||
| //CHECK: call { x86_amx, x86_amx } @llvm.x86.t2rpntlvwz1t1.internal | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 0 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| //CHECK-NEXT: {{%.*}} = extractvalue { x86_amx, x86_amx } {{%.*}}, 1 | ||
| //CHECK-NEXT: {{%.*}} = call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| //CHECK-NEXT: store <256 x i32> {{%.*}}, ptr {{%.*}} | ||
| __tile_2rpntlvwz1t1(&dst0, &dst1, buf, STRIDE); | ||
| } | ||
|
|
||
| void test_tile_transposed(__tile1024i dst, __tile1024i src) { | ||
| //CHECK-LABEL: @test_tile_transposed | ||
| //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) | ||
| //CHECK-DAG: call x86_amx @llvm.x86.ttransposed.internal | ||
| //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) | ||
| __tile_transposed(&dst, src); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown \ | ||
| // RUN: -target-feature +amx-int8 -target-feature +amx-bf16 -target-feature +amx-transpose \ | ||
| // RUN: -target-feature +avx512f -target-feature +amx-element-evex -verify | ||
|
|
||
| #include <immintrin.h> | ||
| #include <stddef.h> | ||
| #include <immintrin.h> | ||
| #include <stddef.h> | ||
|
|
||
| // Transpose | ||
| void test_tile_2rpntlvwz0(const void *A, size_t B) { | ||
| _tile_2rpntlvwz0(8, A, B); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz0t1(const void *A, size_t B) { | ||
| _tile_2rpntlvwz0t1(8, A, B); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1(const void *A, size_t B) { | ||
| _tile_2rpntlvwz1(8, A, B); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| } | ||
|
|
||
| void test_tile_2rpntlvwz1t1(const void *A, size_t B) { | ||
| _tile_2rpntlvwz1t1(8, A, B); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| } | ||
|
|
||
| void test_tile_transposed() | ||
| { | ||
| _tile_transposed(8, 2); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| _tile_transposed(1, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // REQUIRES: x86-registered-target | ||
|
|
||
| // RUN: %clang_cc1 -triple x86_64-unknown-fuchsia -O2 -flto -ffat-lto-objects \ | ||
| // RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -fvisibility=hidden -emit-llvm -o - %s \ | ||
| // RUN: | FileCheck %s | ||
|
|
||
| // CHECK: llvm.embedded.object | ||
| // CHECK-SAME: section ".llvm.lto" | ||
|
|
||
| // CHECK-LABEL: define hidden void @foo | ||
| // CHECK: entry: | ||
| // CHECK-NEXT: %cmp14.not = icmp eq i64 %len, 0 | ||
| // CHECK-NEXT: br i1 %cmp14.not, label %for.end7, label %for.cond1.preheader.preheader | ||
| // CHECK: for.cond1.preheader.preheader: ; preds = %entry | ||
| // CHECK-NEXT: %arrayidx.1 = getelementptr inbounds nuw i8, ptr %ptr, i64 4 | ||
| // CHECK-NEXT: br label %for.cond1.preheader | ||
|
|
||
| // CHECK-NOT: @llvm.type.test | ||
|
|
||
| // The code below is a reduced case from https://github.com/llvm/llvm-project/issues/112053 | ||
| #define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs))) | ||
| typedef void func(void* arg, const char* fmt, ...) __PRINTFLIKE(2, 3); | ||
| typedef __SIZE_TYPE__ size_t; | ||
| typedef unsigned long uintptr_t; | ||
|
|
||
| extern "C" | ||
| void foo(const void* ptr, size_t len, long disp_addr, | ||
| func* printf_func, void* printf_arg) { | ||
| uintptr_t address = (uintptr_t)ptr; | ||
| size_t count; | ||
|
|
||
| for (count = 0; count < len; count += 16) { | ||
| union { | ||
| unsigned int buf[4]; | ||
| unsigned char cbuf[16]; | ||
| } u; | ||
| size_t s = 10; | ||
| size_t i; | ||
|
|
||
| for (i = 0; i < s / 4; i++) { | ||
| u.buf[i] = ((const unsigned int*)address)[i]; | ||
| printf_func(printf_arg, "%08x ", static_cast<unsigned int>(u.buf[i])); | ||
| } | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Test -fprofile-generate-cold-function-coverage | ||
|
|
||
| // RUN: rm -rf %t && split-file %s %t | ||
| // RUN: %clang --target=x86_64 -O2 -fprofile-generate-cold-function-coverage=/xxx/yyy/ -fprofile-sample-accurate -fprofile-sample-use=%t/pgo-cold-func.prof -S -emit-llvm -o - %t/pgo-cold-func.c | FileCheck %s | ||
|
|
||
| // CHECK: @__llvm_profile_filename = {{.*}} c"/xxx/yyy/default_%m.profraw\00" | ||
|
|
||
| // CHECK: store i8 0, ptr @__profc_bar, align 1 | ||
| // CHECK-NOT: @__profc_foo | ||
|
|
||
| //--- pgo-cold-func.prof | ||
| foo:1:1 | ||
| 1: 1 | ||
|
|
||
| //--- pgo-cold-func.c | ||
| int bar(int x) { return x;} | ||
| int foo(int x) { | ||
| return x; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // RUN: %clang -### -c -fprofile-generate-cold-function-coverage %s 2>&1 | FileCheck %s | ||
| // CHECK: "--instrument-cold-function-only-path=default_%m.profraw" | ||
| // CHECK: "--pgo-instrument-cold-function-only" | ||
| // CHECK: "--pgo-function-entry-coverage" | ||
| // CHECK-NOT: "-fprofile-instrument" | ||
| // CHECK-NOT: "-fprofile-instrument-path= | ||
|
|
||
| // RUN: %clang -### -c -fprofile-generate-cold-function-coverage=dir %s 2>&1 | FileCheck %s --check-prefix=CHECK-EQ | ||
| // CHECK-EQ: "--instrument-cold-function-only-path=dir{{/|\\\\}}default_%m.profraw" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // RUN: fir-opt %s --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %s | ||
| // RUN: fir-opt %s --fir-to-llvm-ir="target=x86_64-pc-windows-msvc" | FileCheck %s | ||
|
|
||
| fir.global linkonce_odr @global_linkonce_odr constant : i32 { | ||
| %0 = arith.constant 0 : i32 | ||
| fir.has_value %0 : i32 | ||
| } | ||
|
|
||
| llvm.comdat @__llvm_comdat { | ||
| llvm.comdat_selector @global_linkonce_odr any | ||
| } | ||
|
|
||
| // CHECK-LABEL: llvm.comdat @__llvm_comdat | ||
| // CHECK: llvm.comdat_selector @global_linkonce_odr any |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| //===---------- inline implementation of i386 syscalls ------------* C++ *-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_I386_SYSCALL_H | ||
| #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_I386_SYSCALL_H | ||
|
|
||
| #include "src/__support/common.h" | ||
| #include "src/__support/macros/config.h" | ||
|
|
||
| namespace LIBC_NAMESPACE_DECL { | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" : "=a"(ret) : "a"(num) : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" : "=a"(ret) : "a"(num), "b"(arg1) : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1, long arg2) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" | ||
| : "=a"(ret) | ||
| : "a"(num), "b"(arg1), "c"(arg2) | ||
| : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1, long arg2, long arg3) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" | ||
| : "=a"(ret) | ||
| : "a"(num), "b"(arg1), "c"(arg2), "d"(arg3) | ||
| : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1, long arg2, long arg3, | ||
| long arg4) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" | ||
| : "=a"(ret) | ||
| : "a"(num), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4) | ||
| : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1, long arg2, long arg3, | ||
| long arg4, long arg5) { | ||
| long ret; | ||
| LIBC_INLINE_ASM("int $128" | ||
| : "=a"(ret) | ||
| : "a"(num), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), | ||
| "D"(arg5) | ||
| : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| LIBC_INLINE long syscall_impl(long num, long arg1, long arg2, long arg3, | ||
| long arg4, long arg5, long arg6) { | ||
| long ret; | ||
| LIBC_INLINE_ASM(R"( | ||
| push %[arg6] | ||
| push %%ebp | ||
| mov 4(%%esp), %%ebp | ||
| int $128 | ||
| pop %%ebp | ||
| add $4, %%esp | ||
| )" | ||
| : "=a"(ret) | ||
| : "a"(num), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), | ||
| "D"(arg5), [arg6] "m"(arg6) | ||
| : "memory"); | ||
| return ret; | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE_DECL | ||
|
|
||
| #endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_I386_SYSCALL_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++03 | ||
|
|
||
| #include <cstdint> | ||
| #include <cstddef> | ||
| #include <functional> | ||
|
|
||
| #include "benchmark/benchmark.h" | ||
|
|
||
| #include "GenerateInput.h" | ||
| #include "test_macros.h" | ||
|
|
||
| constexpr std::size_t TestNumInputs = 1024; | ||
|
|
||
| template <class _Size> | ||
| inline TEST_ALWAYS_INLINE _Size loadword(const void* __p) { | ||
| _Size __r; | ||
| std::memcpy(&__r, __p, sizeof(__r)); | ||
| return __r; | ||
| } | ||
|
|
||
| inline TEST_ALWAYS_INLINE std::size_t hash_len_16(std::size_t __u, std::size_t __v) { | ||
| const std::size_t __mul = 0x9ddfea08eb382d69ULL; | ||
| std::size_t __a = (__u ^ __v) * __mul; | ||
| __a ^= (__a >> 47); | ||
| std::size_t __b = (__v ^ __a) * __mul; | ||
| __b ^= (__b >> 47); | ||
| __b *= __mul; | ||
| return __b; | ||
| } | ||
|
|
||
| template <std::size_t _Len> | ||
| inline TEST_ALWAYS_INLINE std::size_t hash_len_0_to_8(const char* __s) { | ||
| static_assert(_Len == 4 || _Len == 8, ""); | ||
| const uint64_t __a = loadword<uint32_t>(__s); | ||
| const uint64_t __b = loadword<uint32_t>(__s + _Len - 4); | ||
| return hash_len_16(_Len + (__a << 3), __b); | ||
| } | ||
|
|
||
| struct UInt32Hash { | ||
| UInt32Hash() = default; | ||
| inline TEST_ALWAYS_INLINE std::size_t operator()(uint32_t data) const { | ||
| return hash_len_0_to_8<4>(reinterpret_cast<const char*>(&data)); | ||
| } | ||
| }; | ||
|
|
||
| template <class HashFn, class GenInputs> | ||
| void BM_Hash(benchmark::State& st, HashFn fn, GenInputs gen) { | ||
| auto in = gen(st.range(0)); | ||
| const auto end = in.data() + in.size(); | ||
| std::size_t last_hash = 0; | ||
| benchmark::DoNotOptimize(&last_hash); | ||
| while (st.KeepRunning()) { | ||
| for (auto it = in.data(); it != end; ++it) { | ||
| benchmark::DoNotOptimize(last_hash += fn(*it)); | ||
| } | ||
| benchmark::ClobberMemory(); | ||
| } | ||
| } | ||
|
|
||
| BENCHMARK_CAPTURE(BM_Hash, uint32_random_std_hash, std::hash<uint32_t>{}, getRandomIntegerInputs<uint32_t>) | ||
| ->Arg(TestNumInputs); | ||
|
|
||
| BENCHMARK_CAPTURE(BM_Hash, uint32_random_custom_hash, UInt32Hash{}, getRandomIntegerInputs<uint32_t>) | ||
| ->Arg(TestNumInputs); | ||
|
|
||
| BENCHMARK_CAPTURE(BM_Hash, uint32_top_std_hash, std::hash<uint32_t>{}, getSortedTopBitsIntegerInputs<uint32_t>) | ||
| ->Arg(TestNumInputs); | ||
|
|
||
| BENCHMARK_CAPTURE(BM_Hash, uint32_top_custom_hash, UInt32Hash{}, getSortedTopBitsIntegerInputs<uint32_t>) | ||
| ->Arg(TestNumInputs); | ||
|
|
||
| BENCHMARK_MAIN(); |