Skip to content

Commit d03a662

Browse files
authored
Execution Tests: Long Vector Bitwise intrinsics (microsoft#7772)
This PR adds tests for the bitwise intrinsics saturate, reversebits, countbits, firstbithigh, and firstbitlow. A new input value set 'Bitwise' was added to include bounadry cases for the respective types. Resolves microsoft#7467
1 parent 4e48d34 commit d03a662

3 files changed

Lines changed: 129 additions & 0 deletions

File tree

tools/clang/unittests/HLSLExec/LongVectorOps.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ INPUT_SET(RangeOne)
1616
INPUT_SET(RangeHalfPi)
1717
INPUT_SET(SplitDouble)
1818
INPUT_SET(BitShiftRhs)
19+
INPUT_SET(Bitwise)
1920

2021
#undef INPUT_SET
2122

@@ -52,6 +53,12 @@ OP_DEFAULT_DEFINES(Bitwise, Not, 1, "TestUnaryOperator", "~",
5253
" -DFUNC_UNARY_OPERATOR=1")
5354
OP(Bitwise, LeftShift, 2, "", "<<", "", Default1, BitShiftRhs, Default3)
5455
OP(Bitwise, RightShift, 2, "", ">>", "", Default1, BitShiftRhs, Default3)
56+
OP_DEFAULT(Bitwise, Saturate, 1, "saturate", "")
57+
OP_DEFAULT(Bitwise, ReverseBits, 1, "reversebits", "")
58+
OP(Bitwise, CountBits, 1, "countbits", "", "", Bitwise, Default2, Default3)
59+
OP(Bitwise, FirstBitHigh, 1, "firstbithigh", "", "", Bitwise, Default2,
60+
Default3)
61+
OP(Bitwise, FirstBitLow, 1, "firstbitlow", "", "", Bitwise, Default2, Default3)
5562

5663
OP_DEFAULT_DEFINES(Unary, Initialize, 1, "TestInitialize", "",
5764
" -DFUNC_INITIALIZE=1")

tools/clang/unittests/HLSLExec/LongVectorTestData.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,41 +251,57 @@ INPUT_SET(InputSet::Default1, -6, 1, 7, 3, 8, 4, -3, 8, 8, -2);
251251
INPUT_SET(InputSet::Default2, 5, -6, -3, -2, 9, 3, 1, -3, -7, 2);
252252
INPUT_SET(InputSet::Default3, 5, -6, -3, -2, 9, 3, 1, -3, -7, 2);
253253
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 12, 13, 14, 15);
254+
INPUT_SET(InputSet::Bitwise, std::numeric_limits<int16_t>::min(), -1, 0, 1, 3,
255+
6, 9, 0x5555, static_cast<int16_t>(0xAAAA),
256+
std::numeric_limits<int16_t>::max());
254257
END_INPUT_SETS()
255258

256259
BEGIN_INPUT_SETS(int32_t)
257260
INPUT_SET(InputSet::Default1, -6, 1, 7, 3, 8, 4, -3, 8, 8, -2);
258261
INPUT_SET(InputSet::Default2, 5, -6, -3, -2, 9, 3, 1, -3, -7, 2);
259262
INPUT_SET(InputSet::Default3, 5, -6, -3, -2, 9, 3, 1, -3, -7, 2);
260263
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 30, 31, 32);
264+
INPUT_SET(InputSet::Bitwise, std::numeric_limits<int32_t>::min(), -1, 0, 1, 3,
265+
6, 9, 0x55555555, static_cast<int32_t>(0xAAAAAAAA),
266+
std::numeric_limits<int32_t>::max());
261267
END_INPUT_SETS()
262268

263269
BEGIN_INPUT_SETS(int64_t)
264270
INPUT_SET(InputSet::Default1, -6, 11, 7, 3, 8, 4, -3, 8, 8, -2);
265271
INPUT_SET(InputSet::Default2, 5, -1337, -3, -2, 9, 3, 1, -3, 501, 2);
266272
INPUT_SET(InputSet::Default3, 5, -1337, -3, -2, 9, 3, 1, -3, 501, 2);
267273
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 62, 63, 64);
274+
INPUT_SET(InputSet::Bitwise, std::numeric_limits<int64_t>::min(), -1, 0, 1, 3,
275+
6, 9, 0x5555555555555555LL, 0xAAAAAAAAAAAAAAAALL,
276+
std::numeric_limits<int64_t>::max());
268277
END_INPUT_SETS()
269278

270279
BEGIN_INPUT_SETS(uint16_t)
271280
INPUT_SET(InputSet::Default1, 1, 699, 3, 1023, 5, 6, 0, 8, 9, 10);
272281
INPUT_SET(InputSet::Default2, 2, 111, 3, 4, 5, 9, 21, 8, 9, 10);
273282
INPUT_SET(InputSet::Default3, 2, 111, 3, 4, 5, 9, 21, 8, 9, 10);
274283
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 12, 13, 14, 15);
284+
INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x5555, 0xAAAA, 0x8000, 127,
285+
std::numeric_limits<uint16_t>::max());
275286
END_INPUT_SETS()
276287

277288
BEGIN_INPUT_SETS(uint32_t)
278289
INPUT_SET(InputSet::Default1, 1, 2, 3, 4, 5, 0, 7, 8, 9, 10);
279290
INPUT_SET(InputSet::Default2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
280291
INPUT_SET(InputSet::Default3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
281292
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 30, 31, 32);
293+
INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x55555555, 0xAAAAAAAA, 0x80000000,
294+
127, std::numeric_limits<uint32_t>::max());
282295
END_INPUT_SETS()
283296

284297
BEGIN_INPUT_SETS(uint64_t)
285298
INPUT_SET(InputSet::Default1, 1, 2, 3, 4, 5, 0, 7, 1000, 9, 10);
286299
INPUT_SET(InputSet::Default2, 1, 2, 1337, 4, 5, 6, 7, 8, 9, 10);
287300
INPUT_SET(InputSet::Default3, 1, 2, 1337, 4, 5, 6, 7, 8, 9, 10);
288301
INPUT_SET(InputSet::BitShiftRhs, 1, 6, 3, 0, 9, 3, 62, 63, 64);
302+
INPUT_SET(InputSet::Bitwise, 0, 1, 3, 6, 9, 0x5555555555555555,
303+
0xAAAAAAAAAAAAAAAA, 0x8000000000000000, 127,
304+
std::numeric_limits<uint64_t>::max());
289305
END_INPUT_SETS()
290306

291307
BEGIN_INPUT_SETS(HLSLHalf_t)

tools/clang/unittests/HLSLExec/LongVectors.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "HlslExecTestUtils.h"
1414

1515
#include <array>
16+
#include <bitset>
1617
#include <iomanip>
1718
#include <optional>
1819
#include <sstream>
@@ -616,12 +617,90 @@ DEFAULT_OP_2(OpType::Ldexp, (A * static_cast<T>(std::pow(2.0f, B))));
616617
// Bitwise
617618
//
618619

620+
template <typename T> T Saturate(T A) {
621+
if (A < static_cast<T>(0.0f))
622+
return static_cast<T>(0.0f);
623+
if (A > static_cast<T>(1.0f))
624+
return static_cast<T>(1.0f);
625+
return A;
626+
}
627+
628+
template <typename T> T ReverseBits(T A) {
629+
T Result = 0;
630+
const size_t NumBits = sizeof(T) * 8;
631+
for (size_t I = 0; I < NumBits; I++) {
632+
Result <<= 1;
633+
Result |= (A & 1);
634+
A >>= 1;
635+
}
636+
return Result;
637+
}
638+
639+
template <typename T> uint32_t CountBits(T A) {
640+
return static_cast<uint32_t>(std::bitset<sizeof(T) * 8>(A).count());
641+
}
642+
643+
// General purpose bit scan from the MSB. Based on the value of LookingForZero
644+
// returns the index of the first high/low bit found.
645+
template <typename T> uint32_t ScanFromMSB(T A, bool LookingForZero) {
646+
if (A == 0)
647+
return ~0;
648+
649+
constexpr uint32_t NumBits = sizeof(T) * 8;
650+
for (int32_t I = NumBits - 1; I >= 0; --I) {
651+
bool BitSet = (A & (static_cast<T>(1) << I)) != 0;
652+
if (BitSet != LookingForZero)
653+
return static_cast<uint32_t>(I);
654+
}
655+
return ~0;
656+
}
657+
658+
template <typename T>
659+
typename std::enable_if<std::is_signed<T>::value, uint32_t>::type
660+
FirstBitHigh(T A) {
661+
const bool IsNegative = A < 0;
662+
return ScanFromMSB(A, IsNegative);
663+
}
664+
665+
template <typename T>
666+
typename std::enable_if<!std::is_signed<T>::value, uint32_t>::type
667+
FirstBitHigh(T A) {
668+
return ScanFromMSB(A, false);
669+
}
670+
671+
template <typename T> uint32_t FirstBitLow(T A) {
672+
const uint32_t NumBits = sizeof(T) * 8;
673+
674+
if (A == 0)
675+
return ~0;
676+
677+
for (uint32_t I = 0; I < NumBits; ++I) {
678+
if (A & (static_cast<T>(1) << I))
679+
return static_cast<T>(I);
680+
}
681+
682+
return ~0;
683+
}
684+
619685
DEFAULT_OP_2(OpType::And, (A & B));
620686
DEFAULT_OP_2(OpType::Or, (A | B));
621687
DEFAULT_OP_2(OpType::Xor, (A ^ B));
622688
DEFAULT_OP_1(OpType::Not, (~A));
623689
DEFAULT_OP_2(OpType::LeftShift, (A << B));
624690
DEFAULT_OP_2(OpType::RightShift, (A >> B));
691+
DEFAULT_OP_1(OpType::Saturate, (Saturate(A)));
692+
DEFAULT_OP_1(OpType::ReverseBits, (ReverseBits(A)));
693+
694+
#define BITWISE_OP(OP, IMPL) \
695+
template <typename T> struct Op<OP, T> : StrictValidation { \
696+
uint32_t operator()(T A) { return IMPL; } \
697+
}
698+
699+
BITWISE_OP(OpType::CountBits, (CountBits(A)));
700+
BITWISE_OP(OpType::FirstBitHigh, (FirstBitHigh(A)));
701+
BITWISE_OP(OpType::FirstBitLow, (FirstBitLow(A)));
702+
703+
#undef BITWISE_OP
625704

626705
//
627706
// Unary
@@ -1238,6 +1317,10 @@ class DxilConf_SM69_Vectorized {
12381317
HLK_TEST(Xor, uint16_t, Vector);
12391318
HLK_TEST(Xor, uint16_t, ScalarOp2);
12401319
HLK_TEST(Not, uint16_t, Vector);
1320+
HLK_TEST(ReverseBits, uint16_t, Vector);
1321+
HLK_TEST(CountBits, uint16_t, Vector);
1322+
HLK_TEST(FirstBitHigh, uint16_t, Vector);
1323+
HLK_TEST(FirstBitLow, uint16_t, Vector);
12411324
HLK_TEST(LeftShift, uint16_t, Vector);
12421325
HLK_TEST(LeftShift, uint16_t, ScalarOp2);
12431326
HLK_TEST(RightShift, uint16_t, Vector);
@@ -1253,6 +1336,10 @@ class DxilConf_SM69_Vectorized {
12531336
HLK_TEST(LeftShift, uint32_t, ScalarOp2);
12541337
HLK_TEST(RightShift, uint32_t, Vector);
12551338
HLK_TEST(RightShift, uint32_t, ScalarOp2);
1339+
HLK_TEST(ReverseBits, uint32_t, Vector);
1340+
HLK_TEST(CountBits, uint32_t, Vector);
1341+
HLK_TEST(FirstBitHigh, uint32_t, Vector);
1342+
HLK_TEST(FirstBitLow, uint32_t, Vector);
12561343
HLK_TEST(And, uint64_t, Vector);
12571344
HLK_TEST(And, uint64_t, ScalarOp2);
12581345
HLK_TEST(Or, uint64_t, Vector);
@@ -1264,6 +1351,10 @@ class DxilConf_SM69_Vectorized {
12641351
HLK_TEST(LeftShift, uint64_t, ScalarOp2);
12651352
HLK_TEST(RightShift, uint64_t, Vector);
12661353
HLK_TEST(RightShift, uint64_t, ScalarOp2);
1354+
HLK_TEST(ReverseBits, uint64_t, Vector);
1355+
HLK_TEST(CountBits, uint64_t, Vector);
1356+
HLK_TEST(FirstBitHigh, uint64_t, Vector);
1357+
HLK_TEST(FirstBitLow, uint64_t, Vector);
12671358
HLK_TEST(And, int16_t, Vector);
12681359
HLK_TEST(And, int16_t, ScalarOp2);
12691360
HLK_TEST(Or, int16_t, Vector);
@@ -1275,6 +1366,10 @@ class DxilConf_SM69_Vectorized {
12751366
HLK_TEST(LeftShift, int16_t, ScalarOp2);
12761367
HLK_TEST(RightShift, int16_t, Vector);
12771368
HLK_TEST(RightShift, int16_t, ScalarOp2);
1369+
HLK_TEST(ReverseBits, int16_t, Vector);
1370+
HLK_TEST(CountBits, int16_t, Vector);
1371+
HLK_TEST(FirstBitHigh, int16_t, Vector);
1372+
HLK_TEST(FirstBitLow, int16_t, Vector);
12781373
HLK_TEST(And, int32_t, Vector);
12791374
HLK_TEST(And, int32_t, ScalarOp2);
12801375
HLK_TEST(Or, int32_t, Vector);
@@ -1286,6 +1381,10 @@ class DxilConf_SM69_Vectorized {
12861381
HLK_TEST(LeftShift, int32_t, ScalarOp2);
12871382
HLK_TEST(RightShift, int32_t, Vector);
12881383
HLK_TEST(RightShift, int32_t, ScalarOp2);
1384+
HLK_TEST(ReverseBits, int32_t, Vector);
1385+
HLK_TEST(CountBits, int32_t, Vector);
1386+
HLK_TEST(FirstBitHigh, int32_t, Vector);
1387+
HLK_TEST(FirstBitLow, int32_t, Vector);
12891388
HLK_TEST(And, int64_t, Vector);
12901389
HLK_TEST(And, int64_t, ScalarOp2);
12911390
HLK_TEST(Or, int64_t, Vector);
@@ -1297,6 +1396,13 @@ class DxilConf_SM69_Vectorized {
12971396
HLK_TEST(LeftShift, int64_t, ScalarOp2);
12981397
HLK_TEST(RightShift, int64_t, Vector);
12991398
HLK_TEST(RightShift, int64_t, ScalarOp2);
1399+
HLK_TEST(ReverseBits, int64_t, Vector);
1400+
HLK_TEST(CountBits, int64_t, Vector);
1401+
HLK_TEST(FirstBitHigh, int64_t, Vector);
1402+
HLK_TEST(FirstBitLow, int64_t, Vector);
1403+
HLK_TEST(Saturate, HLSLHalf_t, Vector);
1404+
HLK_TEST(Saturate, float, Vector);
1405+
HLK_TEST(Saturate, double, Vector);
13001406

13011407
// Unary
13021408

0 commit comments

Comments
 (0)