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+
619685DEFAULT_OP_2 (OpType::And, (A & B));
620686DEFAULT_OP_2 (OpType::Or, (A | B));
621687DEFAULT_OP_2 (OpType::Xor, (A ^ B));
622688DEFAULT_OP_1 (OpType::Not, (~A));
623689DEFAULT_OP_2 (OpType::LeftShift, (A << B));
624690DEFAULT_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