mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

This is applied to the vector types defined in <arm_mve.h> for use with the intrinsics for the ARM MVE vector architecture. Its purpose is to inhibit lax vector conversions, but only in the context of overload resolution of the MVE polymorphic intrinsic functions. This solves an ambiguity problem with polymorphic MVE intrinsics that take a vector and a scalar argument: the scalar argument can often have the wrong integer type due to default integer promotions or unsuffixed literals, and therefore, the type of the vector argument should be considered trustworthy when resolving MVE polymorphism. As part of the same change, I've added the new attribute to the declarations generated by the MveEmitter Tablegen backend (and corrected a namespace issue with the other attribute while I was there). Reviewers: aaron.ballman, dmgreen Reviewed By: aaron.ballman Subscribers: kristof.beyls, JDevlieghere, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D72518
116 lines
5.2 KiB
C
116 lines
5.2 KiB
C
// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -Werror -emit-llvm -o - %s | FileCheck %s
|
|
// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -flax-vector-conversions=all -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;
|
|
|
|
__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(); // 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
|