File: overload-arm-mve.c

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (123 lines) | stat: -rw-r--r-- 5,808 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -fdouble-square-bracket-attributes -Werror -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -fdouble-square-bracket-attributes -verify -fsyntax-only -DERROR_CHECK %s

typedef   signed short      int16_t;
typedef   signed int        int32_t;
typedef   signed long long  int64_t;
typedef unsigned short     uint16_t;
typedef unsigned int       uint32_t;
typedef unsigned long long uint64_t;

typedef __attribute__((neon_vector_type(8), __clang_arm_mve_strict_polymorphism))  int16_t  int16x8_t;
typedef __attribute__((neon_vector_type(4), __clang_arm_mve_strict_polymorphism))  int32_t  int32x4_t;
typedef __attribute__((neon_vector_type(2), __clang_arm_mve_strict_polymorphism))  int64_t  int64x2_t;
typedef __attribute__((neon_vector_type(8), __clang_arm_mve_strict_polymorphism)) uint16_t uint16x8_t;
typedef __attribute__((neon_vector_type(4), __clang_arm_mve_strict_polymorphism)) uint32_t uint32x4_t;
typedef __attribute__((neon_vector_type(2), __clang_arm_mve_strict_polymorphism)) uint64_t uint64x2_t;

// Verify that we can use the [[]] spelling of the attribute.
// We intentionally use the same type alias name to check that both versions
// define the same type.
typedef int16_t [[clang::neon_vector_type(8), clang::__clang_arm_mve_strict_polymorphism]] int16x8_t;

// Verify that we can use the attribute outside of a typedef.
void test_param(int16_t [[clang::neon_vector_type(8), clang::__clang_arm_mve_strict_polymorphism]] int16x8);

__attribute__((overloadable))
int overload(int16x8_t x, int16_t y); // expected-note {{candidate function}}
__attribute__((overloadable))
int overload(int32x4_t x, int32_t y); // expected-note {{candidate function}}
__attribute__((overloadable))
int overload(uint16x8_t x, uint16_t y); // expected-note {{candidate function}}
__attribute__((overloadable))
int overload(uint32x4_t x, uint32_t y); // expected-note {{candidate function}}

int16_t s16;
int32_t s32;
uint16_t u16;
uint32_t u32;

int16x8_t vs16;
int32x4_t vs32;
uint16x8_t vu16;
uint32x4_t vu32;

// ----------------------------------------------------------------------
// Simple cases where the types are correctly matched

// CHECK-LABEL: @test_easy_s16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
int test_easy_s16(void) { return overload(vs16, s16); }

// CHECK-LABEL: @test_easy_u16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
int test_easy_u16(void) { return overload(vu16, u16); }

// CHECK-LABEL: @test_easy_s32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
int test_easy_s32(void) { return overload(vs32, s32); }

// CHECK-LABEL: @test_easy_u32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
int test_easy_u32(void) { return overload(vu32, u32); }

// ----------------------------------------------------------------------
// Do arithmetic on the scalar, and it may get promoted. We still expect the
// same overloads to be selected if that happens.

// CHECK-LABEL: @test_promote_s16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
int test_promote_s16(void) { return overload(vs16, s16 + 1); }

// CHECK-LABEL: @test_promote_u16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
int test_promote_u16(void) { return overload(vu16, u16 + 1); }

// CHECK-LABEL: @test_promote_s32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
int test_promote_s32(void) { return overload(vs32, s32 + 1); }

// CHECK-LABEL: @test_promote_u32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
int test_promote_u32(void) { return overload(vu32, u32 + 1); }

// ----------------------------------------------------------------------
// Write a simple integer literal without qualification, and expect
// the vector type to make it unambiguous which integer type you meant
// the literal to be.

// CHECK-LABEL: @test_literal_s16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
int test_literal_s16(void) { return overload(vs16, 1); }

// CHECK-LABEL: @test_literal_u16(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
int test_literal_u16(void) { return overload(vu16, 1); }

// CHECK-LABEL: @test_literal_s32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
int test_literal_s32(void) { return overload(vs32, 1); }

// CHECK-LABEL: @test_literal_u32(
// CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
int test_literal_u32(void) { return overload(vu32, 1); }

// ----------------------------------------------------------------------
// All of those overload resolutions are supposed to be unambiguous even when
// lax vector conversion is enabled. Check here that a lax conversion in a
// different context still works.
int16x8_t lax_conversion(void) { return vu32; }

// ----------------------------------------------------------------------
// Use a vector type that there really _isn't_ any overload for, and
// make sure that we get a fatal compile error.

#ifdef ERROR_CHECK
int expect_error(uint64x2_t v) {
  return overload(v, 2); // expected-error {{no matching function for call to 'overload'}}
}

typedef __attribute__((__clang_arm_mve_strict_polymorphism)) int i; // expected-error {{'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type}}
typedef __attribute__((__clang_arm_mve_strict_polymorphism)) int f(void); // expected-error {{'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type}}
typedef __attribute__((__clang_arm_mve_strict_polymorphism)) struct { uint16x8_t v; } s; // expected-error {{'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type}}
#endif