Skip to content

Commit

Permalink
Extend hack-undef to convert all nullable types
Browse files Browse the repository at this point in the history
* new test to check that structs get null instead of undef
  * The test avoids google#176
  • Loading branch information
alan-baker authored and dneto0 committed Aug 29, 2018
1 parent 0dd3fd2 commit 9bf93fb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 5 deletions.
47 changes: 42 additions & 5 deletions lib/SPIRVProducerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ struct SPIRVProducerPass final : public ModulePass {
void WriteOperand(SPIRVOperand *Op);
void WriteSPIRVBinary();

// Returns true if |type| is compatible with OpConstantNull.
bool IsTypeNullable(const Type* type) const;

private:
static char ID;
ArrayRef<std::pair<unsigned, std::string>> samplerMap;
Expand Down Expand Up @@ -2265,11 +2268,8 @@ void SPIRVProducerPass::GenerateSPIRVConstants() {
if (isa<UndefValue>(Cst)) {
// Ops[0] = Result Type ID
Opcode = spv::OpUndef;
if (hack_undef) {
Type *type = Cst->getType();
if (type->isFPOrFPVectorTy() || type->isIntOrIntVectorTy()) {
Opcode = spv::OpConstantNull;
}
if (hack_undef && IsTypeNullable(Cst->getType())) {
Opcode = spv::OpConstantNull;
}
} else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
unsigned BitWidth = CI->getBitWidth();
Expand Down Expand Up @@ -6127,3 +6127,40 @@ void SPIRVProducerPass::WriteSPIRVBinary() {
}
}
}

bool SPIRVProducerPass::IsTypeNullable(const Type* type) const {
switch (type->getTypeID()) {
case Type::HalfTyID:
case Type::FloatTyID:
case Type::DoubleTyID:
case Type::IntegerTyID:
case Type::VectorTyID:
return true;
case Type::PointerTyID: {
const PointerType *pointer_type = cast<PointerType>(type);
if (pointer_type->getPointerAddressSpace() !=
AddressSpace::UniformConstant) {
auto pointee_type = pointer_type->getPointerElementType();
if (pointee_type->isStructTy() &&
cast<StructType>(pointee_type)->isOpaque()) {
// Images and samplers are not nullable.
return false;
}
}
return true;
}
case Type::ArrayTyID:
return IsTypeNullable(cast<CompositeType>(type)->getTypeAtIndex(0u));
case Type::StructTyID: {
const StructType* struct_type = cast<StructType>(type);
// Images and samplers are not nullable.
if (struct_type->isOpaque()) return false;
for (const auto element : struct_type->elements()) {
if (!IsTypeNullable(element)) return false;
}
return true;
}
default:
return false;
}
}
28 changes: 28 additions & 0 deletions test/hack_undef_composite.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: clspv %s -S -o %t.spvasm -hack-undef
// RUN: FileCheck %s < %t.spvasm
// RUN: clspv %s -o %t.spv -hack-undef
// RUN: spirv-dis -o %t2.spvasm %t.spv
// RUN: FileCheck %s < %t2.spvasm
// RUN: spirv-val --target-env vulkan1.0 %t.spv

struct a {
int x;
int y;
float arr[5];
};

kernel void foo(global struct a* struct_out, int n) {
struct a local_a;
if (n == 0) {
local_a.x = 0;
}
*struct_out = local_a;
}

// CHECK: [[uint:%[0-9a-zA-Z_]+]] = OpTypeInt 32 0
// CHECK: [[float:%[0-9a-zA-Z_]+]] = OpTypeFloat 32
// CHECK: [[array:%[0-9a-zA-Z_]+]] = OpTypeArray [[float]]
// CHECK: [[struct:%[0-9a-zA-Z_]+]] = OpTypeStruct [[uint]] [[uint]] [[array]]
// CHECK-NOT: OpUndef
// CHECK: OpConstantNull [[struct]]
// CHECK-NOT: OpUndef

0 comments on commit 9bf93fb

Please sign in to comment.