Skip to content

Commit

Permalink
Small improvements
Browse files Browse the repository at this point in the history
- adds some helper functions to Value
- fixes some asan/ubsan complaints
  • Loading branch information
doe300 committed Aug 24, 2019
1 parent e817b2e commit 37002e2
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 21 deletions.
4 changes: 2 additions & 2 deletions cmake/sanitizers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ set(CMAKE_CXX_FLAGS_MSAN "-fsanitize=memory -fno-optimize-sibling-calls -fsaniti

# UndefinedBehaviour
# Run with: UBSAN_OPTIONS=print_stacktrace=1 environment variable
set(CMAKE_C_FLAGS_UBSAN "-fsanitize=undefined -fno-omit-frame-pointer -g -Og")
set(CMAKE_CXX_FLAGS_UBSAN "-fsanitize=undefined -fno-omit-frame-pointer -g -Og")
set(CMAKE_C_FLAGS_UBSAN "-fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-omit-frame-pointer -g -Og")
set(CMAKE_CXX_FLAGS_UBSAN "-fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-omit-frame-pointer -g -Og")
31 changes: 31 additions & 0 deletions src/Values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ Optional<Literal> Value::getLiteralValue() const noexcept
return *lit;
if(auto imm = checkImmediate())
return imm->toLiteral();
if(auto vector = checkVector())
return vector->isAllSame() ? ((*vector)[0]) : Optional<Literal>{};
return {};
}

Expand Down Expand Up @@ -739,6 +741,35 @@ const LocalUser* Value::getSingleWriter() const
return nullptr;
}

bool Value::isUniform() const
{
if(checkImmediate())
return true;
if(checkLiteral())
return true;
if(auto vec = checkVector())
return vec->isAllSame();
if(auto reg = checkRegister())
return *reg == REG_UNIFORM || *reg == REG_QPU_NUMBER || *reg == REG_REV_FLAG;
return isUndefined();
}

Optional<Value> Value::getConstantValue(bool transitive) const
{
if(checkLiteral())
return *this;
if(checkImmediate())
return *this;
if(checkVector())
return *this;
auto reg = checkRegister();
if(reg && (*reg == REG_ELEMENT_NUMBER || *reg == REG_QPU_NUMBER))
return *this;
if(auto loc = checkLocal())
return (transitive && loc->getSingleWriter()) ? loc->getSingleWriter()->precalculate().first : NO_VALUE;
return isUndefined() ? *this : NO_VALUE;
}

Value Value::createZeroInitializer(DataType type)
{
if(type.isScalarType() || type.getPointerType())
Expand Down
26 changes: 26 additions & 0 deletions src/Values.h
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,32 @@ namespace vc4c
*/
const LocalUser* getSingleWriter() const;

/**
* Returns whether this value is an uniform value (a value equal across all SIMD vector elements).
*
* Uniform values are among others:
* - literal values
* - SIMD vectors with all same elements
* - small immediates
* - uniform registers (UNIFORM, QPU number)
*/
bool isUniform() const;

/**
* Returns the constant value "contained" in this value, if any.
*
* A value is considered constant, if it matches one of the conditions:
* - it is a literal value
* - it is a SIMD vector
* - it is a small immediate
* - it is a constant register value
* - it is a local with a single writer writing a constant value (only if transitive flag set)
*
* If the resulting Value is set, it is guaranteed to be either a literal value, a small immediate or a
* register.
*/
Optional<Value> getConstantValue(bool transitive = true) const;

/*
* Creates a zero-initializer Value for the given data-type.
*
Expand Down
6 changes: 2 additions & 4 deletions src/intrinsics/Intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1177,13 +1177,11 @@ static NODISCARD InstructionWalker intrinsifyReadWorkItemInfo(Method& method, In
* -> res = (UNIFORM >> (dim * 8)) & 0xFF
*/
const Local* itemInfo = method.findOrCreateLocal(TYPE_INT32, local);
auto literalDim =
arg.getLiteralValue() ? arg : arg.getSingleWriter() ? arg.getSingleWriter()->precalculate().first : NO_VALUE;
if(literalDim && literalDim->getLiteralValue())
if(auto literalDim = (arg.getConstantValue() & &Value::getLiteralValue))
{
// NOTE: This forces the local_ids/local_sizes values to be on register-file A, but safes an instruction per
// read
switch(literalDim->getLiteralValue()->unsignedInt())
switch(literalDim->unsignedInt())
{
case 0:
return it.reset((new MoveOperation(it->getOutput().value(), itemInfo->createReference()))
Expand Down
4 changes: 2 additions & 2 deletions src/optimization/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ const std::vector<OptimizationPass> Optimizer::ALL_PASSES = {
OptimizationType::INITIAL),
OptimizationPass("MergeBasicBlocks", "merge-blocks", mergeAdjacentBasicBlocks,
"merges adjacent basic blocks if there are no other conflicting transitions", OptimizationType::INITIAL),
OptimizationPass(
"VectorizeLoops", "vectorize-loops", vectorizeLoops, "vectorizes loops (WIP)", OptimizationType::INITIAL),
/*
* The second block executes optimizations only within a single basic block.
* These optimizations may be executed in a loop until there are not more changes to the instructions
*/
OptimizationPass(
"VectorizeLoops", "vectorize-loops", vectorizeLoops, "vectorizes loops (WIP)", OptimizationType::INITIAL),
OptimizationPass("SingleSteps", "single-steps", runSingleSteps,
"runs all the single-step optimizations. Combining them results in fewer iterations over the instructions",
OptimizationType::REPEAT),
Expand Down
2 changes: 1 addition & 1 deletion test/TestEmulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ void TestEmulator::testWorkItem()
// output buffer: 24 * work-items
data.parameter.emplace_back(0, std::vector<uint32_t>(24 * data.calcNumWorkItems()));

// FIXME sometimes succeeds, sometimes fails
// TODO test with global offset != 0
// TODO test with multi dimensions!

const auto result = emulate(data);
TEST_ASSERT(result.executionSuccessful)
Expand Down
6 changes: 4 additions & 2 deletions test/TestExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ TestExpressions::~TestExpressions() = default;

void TestExpressions::testCreation()
{
Module mod{Configuration{}};
Configuration config{};
Module mod{config};
Method method(mod);

method.appendToEnd(new intermediate::BranchLabel(*method.addNewLocal(TYPE_LABEL).local()));
Expand Down Expand Up @@ -117,7 +118,8 @@ void TestExpressions::testCreation()

void TestExpressions::testCombination()
{
Module mod{Configuration{}};
Configuration config{};
Module mod{config};
Method method(mod);
FastMap<const Local*, Expression> expressions;

Expand Down
15 changes: 11 additions & 4 deletions test/emulation_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,17 @@ void copyConvert(const In& in, Out& out)
{
if(out.size() < N)
throw vc4c::CompilationError(vc4c::CompilationStep::GENERAL, "Invalid container size for copy");
auto base = reinterpret_cast<const typename Out::value_type*>(in.data());
// FIXME for copying single-element char/short vectors to int, this still accesses bytes outside of the source
// vector
std::copy(base, base + N, out.data());
if(in.size() * sizeof(typename In::value_type) < N * sizeof(typename Out::value_type))
{
// special case for e.g. copying char/short to unsigned int
auto dest = reinterpret_cast<typename In::value_type*>(out.data());
std::copy(in.data(), in.data() + in.size(), dest);
}
else
{
auto base = reinterpret_cast<const typename Out::value_type*>(in.data());
std::copy(base, base + N, out.data());
}
}

template <typename Type, std::size_t VectorWidth, std::size_t LocalSize, std::size_t NumGroups>
Expand Down
26 changes: 20 additions & 6 deletions test/test_cases.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace vc4c
}

template<typename T>
static std::pair<uint32_t, Optional<std::vector<uint32_t>>> toParameter(const std::vector<T>& values)
std::pair<uint32_t, Optional<std::vector<uint32_t>>> toParameter(const std::vector<T>& values)
{
std::vector<uint32_t> buffer;
buffer.reserve(values.size());
Expand All @@ -62,13 +62,13 @@ namespace vc4c
}

template<typename T>
static std::pair<uint32_t, Optional<std::vector<uint32_t>>> toScalarParameter(T val)
std::pair<uint32_t, Optional<std::vector<uint32_t>>> toScalarParameter(T val)
{
return std::make_pair(bit_cast<T, uint32_t>(val), Optional<std::vector<uint32_t>>{});
}

template<typename T>
static std::vector<T> toRange(T start, T end, T step = 1)
std::vector<T> toRange(T start, T end, T step = 1)
{
std::vector<T> out;
for(T val = start; val != end; val += step)
Expand All @@ -77,7 +77,7 @@ namespace vc4c
}

template<typename T, typename R>
static std::vector<R> transfer(std::vector<T> in, const std::function<R(T)>& func)
std::vector<R> transfer(std::vector<T> in, const std::function<R(T)>& func)
{
std::vector<R> out;
out.resize(in.size());
Expand Down Expand Up @@ -168,10 +168,24 @@ namespace vc4c
std::make_pair(EmulationData(VC4C_ROOT_PATH "testing/OpenCL-CTS/uchar_compare.cl", "test_select",
{toParameter(std::vector<unsigned>{0x01020304}), toParameter(std::vector<unsigned>{0x04020301}), toParameter(std::vector<unsigned>(1))}, {}, maxExecutionCycles),
addVector({}, 2, std::vector<unsigned>{0x04020301})
)
),
std::make_pair(EmulationData(VC4C_ROOT_PATH "testing/test_async_copy.cl", "test_async_copy",
{toParameter(toRange<unsigned>(0, 12*16)), toParameter(std::vector<unsigned>(12*16)), toParameter(std::vector<unsigned>(12*16))}, toConfig(12), maxExecutionCycles),
addVector(addVector({}, 1, toRange<unsigned>(0, 12*16)), 2, toRange<unsigned>(0, 12*16))
),
std::make_pair(EmulationData(VC4C_ROOT_PATH "testing/test_shuffle.cl", "test_shuffle",
{toParameter(std::vector<unsigned>{0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c}), toParameter(std::vector<unsigned>(10*16/sizeof(int32_t)))}, toConfig(1), maxExecutionCycles),
addVector({}, 1, std::vector<unsigned>{0x08040607, 0x010d0c01, 0x0f0e0900, 0x06080304, 0x120b0701, 0x09080f15, 0x01021300, 0x08070d11, 0x10021b1a, 0x17061904, 0x131c0908, 0x0f0e0d1a, 0x10020111, 0x10020111, 0x10020111, 0x10020111,
0x01000000, 0x10000011, 0x02011100, 0x00001002, 0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c, 0, 0, 0, 0, 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x0d0c0b0a, 0x01000f0e, 0x05040302, 0x09080706, 0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203})
),
//TODO need to pass parameter as literal vectors, not buffers
// std::make_pair(EmulationData(VC4C_ROOT_PATH "testing/test_vector.cl", "test_param",
// {toParameter(std::vector<unsigned>{0x40, 0, 0, 0, 0x41, 0, 0, 0, 0x42, 0, 0, 0, 0x43, 0, 0, 0}), toParameter(std::vector<unsigned>{0x15, 0x16, 0x17, 0x18}), toParameter(std::vector<unsigned>(4))}, toConfig(1), maxExecutionCycles),
// addVector({}, 2, std::vector<unsigned>{0x55, 0x57, 0x59, 0x61})
// )
};

//TODO NVIDIA/matrixMul, NVIDIA/transpose, OpenCLIPP/Arithmetic, OpenCLIPP/Logic, OpenCLIPP/Thresholding, test_signedness, test_shuffle, local_private_storage
//TODO NVIDIA/matrixMul, NVIDIA/transpose, OpenCLIPP/Arithmetic, OpenCLIPP/Logic, OpenCLIPP/Thresholding, test_signedness

static std::vector<std::pair<EmulationData, std::map<uint32_t, std::vector<uint32_t>>>> floatTests = {
std::make_pair(EmulationData(VC4C_ROOT_PATH "example/test_instructions.cl", "test_instructions",
Expand Down

0 comments on commit 37002e2

Please sign in to comment.