1 // RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -Werror -emit-llvm -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -triple thumbv8.1m.main-none-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -verify -fsyntax-only -DERROR_CHECK %s
3 
4 typedef   signed short      int16_t;
5 typedef   signed int        int32_t;
6 typedef   signed long long  int64_t;
7 typedef unsigned short     uint16_t;
8 typedef unsigned int       uint32_t;
9 typedef unsigned long long uint64_t;
10 
11 typedef __attribute__((neon_vector_type(8), __clang_arm_mve_strict_polymorphism))  int16_t  int16x8_t;
12 typedef __attribute__((neon_vector_type(4), __clang_arm_mve_strict_polymorphism))  int32_t  int32x4_t;
13 typedef __attribute__((neon_vector_type(2), __clang_arm_mve_strict_polymorphism))  int64_t  int64x2_t;
14 typedef __attribute__((neon_vector_type(8), __clang_arm_mve_strict_polymorphism)) uint16_t uint16x8_t;
15 typedef __attribute__((neon_vector_type(4), __clang_arm_mve_strict_polymorphism)) uint32_t uint32x4_t;
16 typedef __attribute__((neon_vector_type(2), __clang_arm_mve_strict_polymorphism)) uint64_t uint64x2_t;
17 
18 __attribute__((overloadable))
19 int overload(int16x8_t x, int16_t y); // expected-note {{candidate function}}
20 __attribute__((overloadable))
21 int overload(int32x4_t x, int32_t y); // expected-note {{candidate function}}
22 __attribute__((overloadable))
23 int overload(uint16x8_t x, uint16_t y); // expected-note {{candidate function}}
24 __attribute__((overloadable))
25 int overload(uint32x4_t x, uint32_t y); // expected-note {{candidate function}}
26 
27 int16_t s16;
28 int32_t s32;
29 uint16_t u16;
30 uint32_t u32;
31 
32 int16x8_t vs16;
33 int32x4_t vs32;
34 uint16x8_t vu16;
35 uint32x4_t vu32;
36 
37 // ----------------------------------------------------------------------
38 // Simple cases where the types are correctly matched
39 
40 // CHECK-LABEL: @test_easy_s16(
41 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
test_easy_s16(void)42 int test_easy_s16(void) { return overload(vs16, s16); }
43 
44 // CHECK-LABEL: @test_easy_u16(
45 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
test_easy_u16(void)46 int test_easy_u16(void) { return overload(vu16, u16); }
47 
48 // CHECK-LABEL: @test_easy_s32(
49 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
test_easy_s32(void)50 int test_easy_s32(void) { return overload(vs32, s32); }
51 
52 // CHECK-LABEL: @test_easy_u32(
53 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
test_easy_u32(void)54 int test_easy_u32(void) { return overload(vu32, u32); }
55 
56 // ----------------------------------------------------------------------
57 // Do arithmetic on the scalar, and it may get promoted. We still expect the
58 // same overloads to be selected if that happens.
59 
60 // CHECK-LABEL: @test_promote_s16(
61 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
test_promote_s16(void)62 int test_promote_s16(void) { return overload(vs16, s16 + 1); }
63 
64 // CHECK-LABEL: @test_promote_u16(
65 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
test_promote_u16(void)66 int test_promote_u16(void) { return overload(vu16, u16 + 1); }
67 
68 // CHECK-LABEL: @test_promote_s32(
69 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
test_promote_s32(void)70 int test_promote_s32(void) { return overload(vs32, s32 + 1); }
71 
72 // CHECK-LABEL: @test_promote_u32(
73 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
test_promote_u32(void)74 int test_promote_u32(void) { return overload(vu32, u32 + 1); }
75 
76 // ----------------------------------------------------------------------
77 // Write a simple integer literal without qualification, and expect
78 // the vector type to make it unambiguous which integer type you meant
79 // the literal to be.
80 
81 // CHECK-LABEL: @test_literal_s16(
82 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int16
test_literal_s16(void)83 int test_literal_s16(void) { return overload(vs16, 1); }
84 
85 // CHECK-LABEL: @test_literal_u16(
86 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint16
test_literal_u16(void)87 int test_literal_u16(void) { return overload(vu16, 1); }
88 
89 // CHECK-LABEL: @test_literal_s32(
90 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_int32
test_literal_s32(void)91 int test_literal_s32(void) { return overload(vs32, 1); }
92 
93 // CHECK-LABEL: @test_literal_u32(
94 // CHECK: call i32 @_Z8overload{{[a-zA-Z0-9_]+}}_uint32
test_literal_u32(void)95 int test_literal_u32(void) { return overload(vu32, 1); }
96 
97 // ----------------------------------------------------------------------
98 // All of those overload resolutions are supposed to be unambiguous even when
99 // lax vector conversion is enabled. Check here that a lax conversion in a
100 // different context still works.
lax_conversion(void)101 int16x8_t lax_conversion(void) { return vu32; }
102 
103 // ----------------------------------------------------------------------
104 // Use a vector type that there really _isn't_ any overload for, and
105 // make sure that we get a fatal compile error.
106 
107 #ifdef ERROR_CHECK
expect_error(uint64x2_t v)108 int expect_error(uint64x2_t v) {
109   return overload(v, 2); // expected-error {{no matching function for call to 'overload'}}
110 }
111 
112 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}}
113 typedef __attribute__((__clang_arm_mve_strict_polymorphism)) int f(); // expected-error {{'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type}}
114 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}}
115 #endif
116