7
7
//
8
8
// ===----------------------------------------------------------------------===//
9
9
10
+ // Implements vec and __swizzled_vec__ classes.
11
+
10
12
#pragma once
11
13
14
+ // Define __NO_EXT_VECTOR_TYPE_ON_HOST__ to avoid using ext_vector_type
15
+ // extension even if the host compiler supports it. The same can be
16
+ // accomplished by -D__NO_EXT_VECTOR_TYPE_ON_HOST__ command line option.
17
+ #ifndef __NO_EXT_VECTOR_TYPE_ON_HOST__
18
+ // #define __NO_EXT_VECTOR_TYPE_ON_HOST__
19
+ #endif
20
+
21
+ // Check if Clang's ext_vector_type attribute is available. Host compiler
22
+ // may not be Clang, and Clang may not be built with the extension.
23
+ #ifdef __clang__
24
+ #ifndef __has_extension
25
+ #define __has_extension (x ) 0
26
+ #endif
27
+ #ifdef __HAS_EXT_VECTOR_TYPE__
28
+ #error "Undefine __HAS_EXT_VECTOR_TYPE__ macro"
29
+ #endif
30
+ #if __has_extension(attribute_ext_vector_type)
31
+ #define __HAS_EXT_VECTOR_TYPE__
32
+ #endif
33
+ #endif // __clang__
34
+
35
+ #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
36
+ #error "Undefine __SYCL_USE_EXT_VECTOR_TYPE__ macro"
37
+ #endif
38
+ #ifdef __HAS_EXT_VECTOR_TYPE__
39
+ #if defined(__SYCL_DEVICE_ONLY__) || !defined(__NO_EXT_VECTOR_TYPE_ON_HOST__)
40
+ #define __SYCL_USE_EXT_VECTOR_TYPE__
41
+ #endif
42
+ #elif defined(__SYCL_DEVICE_ONLY__)
43
+ // This is a soft error. We expect the device compiler to have ext_vector_type
44
+ // support, but that should not be a hard requirement.
45
+ #error "SYCL device compiler is built without ext_vector_type support"
46
+ #endif // __HAS_EXT_VECTOR_TYPE__
47
+
12
48
#include < CL/sycl/detail/common.hpp>
13
49
14
- #ifndef __SYCL_DEVICE_ONLY__
15
- #include < algorithm>
16
- #include < functional>
17
- #endif // __SYCL_DEVICE_ONLY__
18
50
// 4.10.1: Scalar data types
19
51
// 4.10.2: SYCL vector types
20
52
@@ -183,6 +215,19 @@ template <typename T> struct LShift {
183
215
}
184
216
};
185
217
218
+ template <typename T, typename convertT, rounding_mode roundingMode>
219
+ T convertHelper (const T &Opnd) {
220
+ if (roundingMode == rounding_mode::automatic ||
221
+ roundingMode == rounding_mode::rtz) {
222
+ return static_cast <convertT>(Opnd);
223
+ }
224
+ if (roundingMode == rounding_mode::rtp) {
225
+ return static_cast <convertT>(ceil (Opnd));
226
+ }
227
+ // roundingMode == rounding_mode::rtn
228
+ return static_cast <convertT>(floor (Opnd));
229
+ }
230
+
186
231
} // namespace detail
187
232
188
233
template <typename DataT, int NumElements> class vec {
@@ -338,7 +383,7 @@ template <typename DataT, int NumElements> class vec {
338
383
void dump () {
339
384
#ifndef __SYCL_DEVICE_ONLY__
340
385
for (int I = 0 ; I < NumElements; ++I) {
341
- std::cout << " " << I << " : " << m_Data. s [I] << std::endl;
386
+ std::cout << " " << I << " : " << getValue (I) << std::endl;
342
387
}
343
388
std::cout << std::endl;
344
389
#endif // __SYCL_DEVICE_ONLY__
@@ -361,12 +406,20 @@ template <typename DataT, int NumElements> class vec {
361
406
size_t get_count () const { return NumElements; }
362
407
size_t get_size () const { return sizeof (m_Data); }
363
408
364
- // TODO: convert() for FP types . Also, check whether rounding mode handling
409
+ // TODO: convert() for FP to FP . Also, check whether rounding mode handling
365
410
// is needed for integers to FP convert.
366
- // template <typename convertT, rounding_mode roundingMode>
367
- // vec<convertT, NumElements> convert() const;
411
+ //
412
+ // Convert to same type is no-op.
413
+ template <typename convertT, rounding_mode roundingMode>
414
+ typename std::enable_if<std::is_same<DataT, convertT>::value,
415
+ vec<convertT, NumElements>>::type
416
+ convert () const {
417
+ return *this ;
418
+ }
419
+ // From Integer to Integer or FP
368
420
template <typename convertT, rounding_mode roundingMode>
369
- typename std::enable_if<std::is_integral<DataT>::value,
421
+ typename std::enable_if<!std::is_same<DataT, convertT>::value &&
422
+ std::is_integral<DataT>::value,
370
423
vec<convertT, NumElements>>::type
371
424
convert () const {
372
425
vec<convertT, NumElements> Result;
@@ -375,6 +428,20 @@ template <typename DataT, int NumElements> class vec {
375
428
}
376
429
return Result;
377
430
}
431
+ // From FP to Integer
432
+ template <typename convertT, rounding_mode roundingMode>
433
+ typename std::enable_if<!std::is_same<DataT, convertT>::value &&
434
+ std::is_integral<convertT>::value &&
435
+ std::is_floating_point<DataT>::value,
436
+ vec<convertT, NumElements>>::type
437
+ convert () const {
438
+ vec<convertT, NumElements> Result;
439
+ for (size_t I = 0 ; I < NumElements; ++I) {
440
+ Result.setValue (
441
+ I, detail::convertHelper<convertT, roundingMode>(getValue (I)));
442
+ }
443
+ return Result;
444
+ }
378
445
379
446
template <typename asT>
380
447
typename std::enable_if<sizeof (asT) == sizeof (DataType), asT>::type
@@ -415,12 +482,24 @@ template <typename DataT, int NumElements> class vec {
415
482
#endif
416
483
#define __SYCL_LOADSTORE (Space ) \
417
484
void load (size_t Offset, multi_ptr<DataT, Space> Ptr) { \
418
- m_Data = *multi_ptr<DataType, Space>(static_cast <DataType *>( \
419
- static_cast <void *>(Ptr + Offset * NumElements))); \
485
+ if (NumElements != 3 ) { \
486
+ m_Data = *multi_ptr<DataType, Space>(static_cast <DataType *>( \
487
+ static_cast <void *>(Ptr + Offset * NumElements))); \
488
+ return ; \
489
+ } \
490
+ for (int I = 0 ; I < NumElements; I++) { \
491
+ setValue (I, *multi_ptr<DataT, Space>(Ptr + Offset * NumElements + I)); \
492
+ } \
420
493
} \
421
494
void store (size_t Offset, multi_ptr<DataT, Space> Ptr) const { \
422
- *multi_ptr<DataType, Space>(static_cast <DataType *>( \
423
- static_cast <void *>(Ptr + Offset * NumElements))) = m_Data; \
495
+ if (NumElements != 3 ) { \
496
+ *multi_ptr<DataType, Space>(static_cast <DataType *>( \
497
+ static_cast <void *>(Ptr + Offset * NumElements))) = m_Data; \
498
+ return ; \
499
+ } \
500
+ for (int I = 0 ; I < NumElements; I++) { \
501
+ *multi_ptr<DataT, Space>(Ptr + Offset * NumElements + I) = getValue (I); \
502
+ } \
424
503
}
425
504
426
505
__SYCL_LOADSTORE (access::address_space::global_space)
@@ -433,7 +512,7 @@ template <typename DataT, int NumElements> class vec {
433
512
#error "Undefine __SYCL_BINOP macro"
434
513
#endif
435
514
436
- #ifdef __SYCL_DEVICE_ONLY__
515
+ #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
437
516
#define __SYCL_BINOP (BINOP, OPASSIGN ) \
438
517
vec operator BINOP (const vec &Rhs) const { \
439
518
vec Ret; \
@@ -457,7 +536,7 @@ template <typename DataT, int NumElements> class vec {
457
536
*this = *this BINOP vec (Rhs); \
458
537
return *this ; \
459
538
}
460
- #else // __SYCL_DEVICE_ONLY__
539
+ #else // __SYCL_USE_EXT_VECTOR_TYPE__
461
540
#define __SYCL_BINOP (BINOP, OPASSIGN ) \
462
541
vec operator BINOP (const vec &Rhs) const { \
463
542
vec Ret; \
@@ -483,7 +562,7 @@ template <typename DataT, int NumElements> class vec {
483
562
*this = *this BINOP vec (Rhs); \
484
563
return *this ; \
485
564
}
486
- #endif // __SYCL_DEVICE_ONLY__
565
+ #endif // __SYCL_USE_EXT_VECTOR_TYPE__
487
566
488
567
__SYCL_BINOP (+, +=)
489
568
__SYCL_BINOP(-, -=)
@@ -588,21 +667,21 @@ template <typename DataT, int NumElements> class vec {
588
667
vec<DataT, NumElements>
589
668
operatorHelper (const vec<DataT, NumElements> &Rhs) const {
590
669
vec<DataT, NumElements> Result;
591
- #ifdef __SYCL_DEVICE_ONLY__
670
+ #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
592
671
Operation<DataType> Op;
593
672
Result.m_Data = Op (m_Data, Rhs.m_Data );
594
- #else // __SYCL_DEVICE_ONLY__
673
+ #else // __SYCL_USE_EXT_VECTOR_TYPE__
595
674
Operation<DataT> Op;
596
675
for (size_t I = 0 ; I < NumElements; ++I) {
597
676
Result.setValue (I, Op (Rhs.getValue (I), getValue (I)));
598
677
}
599
- #endif // __SYCL_DEVICE_ONLY__
678
+ #endif // __SYCL_USE_EXT_VECTOR_TYPE__
600
679
return Result;
601
680
}
602
681
603
682
// setValue and getValue should be able to operate on different underlying
604
683
// types: enum cl_float#N , builtin vector float#N, builtin type float.
605
- #ifdef __SYCL_DEVICE_ONLY__
684
+ #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
606
685
template <int Num = NumElements,
607
686
typename = typename std::enable_if<1 != Num>::type>
608
687
void setValue (int Index, const DataT &Value, int ) {
@@ -614,7 +693,7 @@ template <typename DataT, int NumElements> class vec {
614
693
DataT getValue (int Index, int ) const {
615
694
return m_Data[Index];
616
695
}
617
- #else
696
+ #else // __SYCL_USE_EXT_VECTOR_TYPE__
618
697
template <int Num = NumElements,
619
698
typename = typename std::enable_if<1 != Num>::type>
620
699
void setValue (int Index, const DataT &Value, int ) {
@@ -626,7 +705,7 @@ template <typename DataT, int NumElements> class vec {
626
705
DataT getValue (int Index, int ) const {
627
706
return m_Data.s [Index];
628
707
}
629
- #endif
708
+ #endif // __SYCL_USE_EXT_VECTOR_TYPE__
630
709
631
710
template <int Num = NumElements,
632
711
typename = typename std::enable_if<1 == Num>::type>
@@ -1275,7 +1354,7 @@ class SwizzleOp {
1275
1354
template <typename T, int Num> \
1276
1355
typename std::enable_if<std::is_fundamental<T>::value, vec<T, Num>>::type \
1277
1356
operator BINOP (const T &Lhs, const vec<T, Num> &Rhs) { \
1278
- return vec<T, Num>(static_cast <T>( Lhs)) BINOP Rhs; \
1357
+ return vec<T, Num>(Lhs) BINOP Rhs; \
1279
1358
} \
1280
1359
template <typename VecT, typename OperationLeftT, typename OperationRightT, \
1281
1360
template <typename > class OperationCurrentT , int ... Indexes, \
@@ -1367,7 +1446,7 @@ __SYCL_RELLOGOP(||)
1367
1446
} // namespace sycl
1368
1447
} // namespace cl
1369
1448
1370
- #ifdef __SYCL_DEVICE_ONLY__
1449
+ #ifdef __SYCL_USE_EXT_VECTOR_TYPE__
1371
1450
typedef char __char_t ;
1372
1451
typedef char __char2_vec_t __attribute__ ((ext_vector_type(2 )));
1373
1452
typedef char __char3_vec_t __attribute__ ((ext_vector_type(3 )));
@@ -1461,7 +1540,7 @@ typedef double __double16_vec_t __attribute__((ext_vector_type(16)));
1461
1540
1462
1541
#define GET_CL_TYPE (target, num ) __##target##num##_vec_t
1463
1542
#define GET_SCALAR_CL_TYPE (target ) target
1464
- #else // __SYCL_DEVICE_ONLY__
1543
+ #else // __SYCL_USE_EXT_VECTOR_TYPE__
1465
1544
// For signed char. OpenCL doesn't have any type about `signed char`, therefore
1466
1545
// we use type alias of cl_char instead.
1467
1546
using cl_schar = cl_char;
@@ -1473,7 +1552,7 @@ using cl_schar16 = cl_char16;
1473
1552
1474
1553
#define GET_CL_TYPE (target, num ) cl_##target##num
1475
1554
#define GET_SCALAR_CL_TYPE (target ) cl_##target
1476
- #endif // __SYCL_DEVICE_ONLY__
1555
+ #endif // __SYCL_USE_EXT_VECTOR_TYPE__
1477
1556
1478
1557
namespace cl {
1479
1558
namespace sycl {
@@ -1484,6 +1563,12 @@ namespace sycl {
1484
1563
using DataType = GET_CL_TYPE(base, num); \
1485
1564
};
1486
1565
1566
+ #define DECLARE_LONGLONG_CONVERTER (base, num ) \
1567
+ template <> class BaseCLTypeConverter <base##long , num> { \
1568
+ public: \
1569
+ using DataType = ::GET_CL_TYPE(base, num); \
1570
+ };
1571
+
1487
1572
#define DECLARE_VECTOR_CONVERTERS (base ) \
1488
1573
namespace detail { \
1489
1574
DECLARE_CONVERTER (base, 2 ) \
@@ -1497,6 +1582,19 @@ namespace sycl {
1497
1582
}; \
1498
1583
} // namespace detail
1499
1584
1585
+ #define DECLARE_VECTOR_LONGLONG_CONVERTERS (base ) \
1586
+ namespace detail { \
1587
+ DECLARE_LONGLONG_CONVERTER (base, 2 ) \
1588
+ DECLARE_LONGLONG_CONVERTER (base, 3 ) \
1589
+ DECLARE_LONGLONG_CONVERTER (base, 4 ) \
1590
+ DECLARE_LONGLONG_CONVERTER (base, 8 ) \
1591
+ DECLARE_LONGLONG_CONVERTER (base, 16 ) \
1592
+ template <> class BaseCLTypeConverter <base##long , 1 > { \
1593
+ public: \
1594
+ using DataType = GET_SCALAR_CL_TYPE(base); \
1595
+ }; \
1596
+ } // namespace detail
1597
+
1500
1598
#define DECLARE_SYCL_VEC_WO_CONVERTERS (base ) \
1501
1599
using cl_##base##16 = vec<base, 16 >; \
1502
1600
using cl_##base##8 = vec<base, 8 >; \
@@ -1510,11 +1608,40 @@ namespace sycl {
1510
1608
using base##3 = cl_##base##3 ; \
1511
1609
using base##2 = cl_##base##2 ;
1512
1610
1611
+ #define DECLARE_SYCL_VEC_CHAR_WO_CONVERTERS \
1612
+ using cl_char16 = vec<signed char , 16 >; \
1613
+ using cl_char8 = vec<signed char , 8 >; \
1614
+ using cl_char4 = vec<signed char , 4 >; \
1615
+ using cl_char3 = vec<signed char , 3 >; \
1616
+ using cl_char2 = vec<signed char , 2 >; \
1617
+ using cl_char = signed char ; \
1618
+ using char16 = vec<char , 16 >; \
1619
+ using char8 = vec<char , 8 >; \
1620
+ using char4 = vec<char , 4 >; \
1621
+ using char3 = vec<char , 3 >; \
1622
+ using char2 = vec<char , 2 >;
1623
+
1624
+ // cl_longlong/cl_ulonglong are not supported in SYCL
1625
+ #define DECLARE_SYCL_VEC_LONGLONG_WO_CONVERTERS (base ) \
1626
+ using base##long16 = vec<base##long , 16 >; \
1627
+ using base##long8 = vec<base##long , 8 >; \
1628
+ using base##long4 = vec<base##long , 4 >; \
1629
+ using base##long3 = vec<base##long , 3 >; \
1630
+ using base##long2 = vec<base##long , 2 >;
1631
+
1513
1632
#define DECLARE_SYCL_VEC (base ) \
1514
1633
DECLARE_VECTOR_CONVERTERS (base) \
1515
1634
DECLARE_SYCL_VEC_WO_CONVERTERS(base)
1516
1635
1517
- DECLARE_SYCL_VEC (char )
1636
+ #define DECLARE_SYCL_VEC_CHAR \
1637
+ DECLARE_VECTOR_CONVERTERS (char ) \
1638
+ DECLARE_SYCL_VEC_CHAR_WO_CONVERTERS
1639
+
1640
+ #define DECLARE_SYCL_VEC_LONGLONG (base ) \
1641
+ DECLARE_VECTOR_LONGLONG_CONVERTERS (base) \
1642
+ DECLARE_SYCL_VEC_LONGLONG_WO_CONVERTERS(base)
1643
+
1644
+ DECLARE_SYCL_VEC_CHAR
1518
1645
DECLARE_SYCL_VEC(schar)
1519
1646
DECLARE_SYCL_VEC(uchar)
1520
1647
DECLARE_SYCL_VEC(short )
@@ -1523,9 +1650,8 @@ DECLARE_SYCL_VEC(int)
1523
1650
DECLARE_SYCL_VEC(uint)
1524
1651
DECLARE_SYCL_VEC(long )
1525
1652
DECLARE_SYCL_VEC(ulong)
1526
- // TODO: Fix long long and unsigned long long.
1527
- // DECLARE_SYCL_VEC(longlong)
1528
- // DECLARE_SYCL_VEC(ulonglong)
1653
+ DECLARE_SYCL_VEC_LONGLONG(long )
1654
+ DECLARE_SYCL_VEC_LONGLONG(ulong)
1529
1655
DECLARE_SYCL_VEC(float )
1530
1656
DECLARE_SYCL_VEC(double )
1531
1657
// TODO: Fix half.
0 commit comments