-
Notifications
You must be signed in to change notification settings - Fork 18
Add comparison rule, tolerance if applicable, and hex64 view to test failure text output #291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
796dd2e
d2f03d1
1dccd9c
21c5b1e
78467e7
d9ee686
db2f5ea
cde6fee
f8fd606
7a7634a
edb7c30
bb0b384
0d167eb
4bc8e29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,11 +10,13 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "Support/Check.h" | ||
#include "Support/Pipeline.h" | ||
#include "llvm/ADT/APFloat.h" | ||
#include "llvm/ADT/APInt.h" | ||
#include "llvm/Support/Error.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
#include <cmath> | ||
#include <sstream> | ||
|
||
constexpr uint16_t Float16BitSign = 0x8000; | ||
constexpr uint16_t Float16BitExp = 0x7c00; | ||
|
@@ -267,30 +269,118 @@ static bool testBufferFloatULP(offloadtest::Buffer *B1, offloadtest::Buffer *B2, | |
return false; | ||
} | ||
|
||
template <typename T> | ||
static std::string bitPatternAsHex64(const T &Val, | ||
offloadtest::Rule ComparisonRule) { | ||
static_assert(sizeof(T) <= sizeof(uint64_t), "Type too large for Hex64"); | ||
|
||
std::ostringstream Oss; | ||
if (ComparisonRule == offloadtest::Rule::BufferExact) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use llvm::raw_svector_ostream to avoid the include of ? Or is not able to handle the conversion of std::hex? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The std library is the only thing aware of std::hex, unfortunately none of the other llvm ostreams are compatible with std::hex / hexfloat. |
||
Oss << std::hex << Val; | ||
else | ||
Oss << std::hexfloat << Val; | ||
return Oss.str(); | ||
} | ||
|
||
template <typename T> | ||
std::string formatBuffer(offloadtest::Buffer *B, offloadtest::Rule rule) { | ||
llvm::MutableArrayRef<T> arr(reinterpret_cast<T *>(B->Data.get()), | ||
B->Size / sizeof(T)); | ||
if (arr.empty()) | ||
return ""; | ||
|
||
std::string result = "[ " + bitPatternAsHex64(arr[0], rule); | ||
for (size_t i = 1; i < arr.size(); ++i) | ||
result += ", " + bitPatternAsHex64(arr[i], rule); | ||
result += " ]"; | ||
return result; | ||
} | ||
|
||
static const std::string getBufferStr(offloadtest::Buffer *B, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you, but I think it would be cleaner to use templates for this instead of a macro. Also includes a simplification of the logic of the for loop formatting the output string. Edit: After writing this comment I see the same pattern used elsewhere in Pipeline.cpp. The templated version still seems cleaner IMO. And I do see the same pattern with ENUM_CASE in pipeline.h as well, but all of those cases have very simple logic in the macro. I'll still leave the decision up to you. Something like this: template <typename T>
std::string formatBuffer(offloadtest::Buffer* B, offloadtest::Rule rule) {
llvm::MutableArrayRef<T> arr(reinterpret_cast<T*>(B->Data.get()), B->Size / sizeof(T));
if (arr.empty()) return "";
std::string result = "[ " + bitPatternAsHex64(arr[0], rule);
for (size_t i = 1; i < arr.size(); ++i)
result += ", " + bitPatternAsHex64(arr[i], rule);
result += " ]";
return result;
}
static const std::string getBufferStr(offloadtest::Buffer* B, offloadtest::Rule rule) {
using DF = offloadtest::DataFormat;
switch (B->Format) {
case DF::Hex8: return formatBuffer<llvm::yaml::Hex8>(B, rule);
case DF::Hex16: return formatBuffer<llvm::yaml::Hex16>(B, rule);
case DF::Hex32: return formatBuffer<llvm::yaml::Hex32>(B, rule);
case DF::Hex64: return formatBuffer<llvm::yaml::Hex64>(B, rule);
case DF::UInt16: return formatBuffer<uint16_t>(B, rule);
case DF::UInt32: return formatBuffer<uint32_t>(B, rule);
case DF::UInt64: return formatBuffer<uint64_t>(B, rule);
case DF::Int16: return formatBuffer<int16_t>(B, rule);
case DF::Int32: return formatBuffer<int32_t>(B, rule);
case DF::Int64: return formatBuffer<int64_t>(B, rule);
case DF::Float16: return formatBuffer<llvm::yaml::Hex16>(B, rule); // assuming no native float16
case DF::Float32: return formatBuffer<float>(B, rule);
case DF::Float64: return formatBuffer<double>(B, rule);
case DF::Bool: return formatBuffer<uint32_t>(B, rule); // Because sizeof(bool) is 1 but HLSL represents a bool using 4 bytes.
default: return "UHO SCOOBY";
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would +1 on the templated version fwiw There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed Pipeline.cpp and Check.cpp, I think I should leave pipeline.h as is. |
||
offloadtest::Rule rule) { | ||
using DF = offloadtest::DataFormat; | ||
switch (B->Format) { | ||
case DF::Hex8: | ||
return formatBuffer<llvm::yaml::Hex8>(B, rule); | ||
case DF::Hex16: | ||
return formatBuffer<llvm::yaml::Hex16>(B, rule); | ||
case DF::Hex32: | ||
return formatBuffer<llvm::yaml::Hex32>(B, rule); | ||
case DF::Hex64: | ||
return formatBuffer<llvm::yaml::Hex64>(B, rule); | ||
case DF::UInt16: | ||
return formatBuffer<uint16_t>(B, rule); | ||
case DF::UInt32: | ||
return formatBuffer<uint32_t>(B, rule); | ||
case DF::UInt64: | ||
return formatBuffer<uint64_t>(B, rule); | ||
case DF::Int16: | ||
return formatBuffer<int16_t>(B, rule); | ||
case DF::Int32: | ||
return formatBuffer<int32_t>(B, rule); | ||
case DF::Int64: | ||
return formatBuffer<int64_t>(B, rule); | ||
case DF::Float16: | ||
return formatBuffer<llvm::yaml::Hex16>(B, | ||
rule); // assuming no native float16 | ||
case DF::Float32: | ||
return formatBuffer<float>(B, rule); | ||
case DF::Float64: | ||
return formatBuffer<double>(B, rule); | ||
case DF::Bool: | ||
return formatBuffer<uint32_t>(B, | ||
rule); // Because sizeof(bool) is 1 but HLSL | ||
// represents a bool using 4 bytes. | ||
} | ||
} | ||
|
||
llvm::Error verifyResult(offloadtest::Result R) { | ||
llvm::SmallString<256> Str; | ||
llvm::raw_svector_ostream OS(Str); | ||
OS << "Test failed: " << R.Name << "\n"; | ||
|
||
switch (R.ComparisonRule) { | ||
case offloadtest::Rule::BufferExact: { | ||
if (testBufferExact(R.ActualPtr, R.ExpectedPtr)) | ||
return llvm::Error::success(); | ||
OS << "Comparison Rule: BufferExact\n"; | ||
break; | ||
} | ||
case offloadtest::Rule::BufferFloatULP: { | ||
if (testBufferFloatULP(R.ActualPtr, R.ExpectedPtr, R.ULPT, R.DM)) | ||
return llvm::Error::success(); | ||
OS << "Comparison Rule: BufferFloatULP\nULP: " << R.ULPT << "\n"; | ||
break; | ||
} | ||
case offloadtest::Rule::BufferFloatEpsilon: { | ||
if (testBufferFloatEpsilon(R.ActualPtr, R.ExpectedPtr, R.Epsilon, R.DM)) | ||
return llvm::Error::success(); | ||
|
||
std::ostringstream Oss; | ||
Oss << std::defaultfloat << R.Epsilon; | ||
OS << "Comparison Rule: BufferFloatEpsilon\nEpsilon: " << Oss.str() << "\n"; | ||
break; | ||
} | ||
} | ||
llvm::SmallString<256> Str; | ||
llvm::raw_svector_ostream OS(Str); | ||
OS << "Test failed: " << R.Name << "\nExpected:\n"; | ||
|
||
OS << "Expected:\n"; | ||
llvm::yaml::Output YAMLOS(OS); | ||
YAMLOS << *R.ExpectedPtr; | ||
OS << "Got:\n"; | ||
YAMLOS << *R.ActualPtr; | ||
|
||
// Now print exact hex64 representations of each element of the | ||
// actual and expected buffers. | ||
|
||
const std::string ExpectedBufferStr = | ||
getBufferStr(R.ExpectedPtr, R.ComparisonRule); | ||
const std::string ActualBufferStr = | ||
getBufferStr(R.ActualPtr, R.ComparisonRule); | ||
|
||
OS << "Full Hex 64bit representation of Expected Buffer Values:\n" | ||
<< ExpectedBufferStr << "\n"; | ||
OS << "Full Hex 64bit representation of Actual Buffer Values:\n" | ||
<< ActualBufferStr << "\n"; | ||
|
||
return llvm::createStringError(Str.c_str()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Do we want to add a test case of the correct error message output?
We could use
FileCheck
to ensure the hex values or whatnot are being formatted as expected