Skip to content

Commit a871fc4

Browse files
authored
Minimal opt support for SPV_KHR_untyped_pointers (KhronosGroup#6087)
* Added support for global OpUntypedVariableKHR in IRLoader * Added support for untyped pointers as Pointer types using a null element * Updates to type manager * No specific pass allowances yet, but untyped pointers no longer break the whole pipeline
1 parent 2e7ba02 commit a871fc4

File tree

7 files changed

+66
-21
lines changed

7 files changed

+66
-21
lines changed

source/opt/ir_loader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
207207
} else if (IsTypeInst(opcode)) {
208208
module_->AddType(std::move(spv_inst));
209209
} else if (IsConstantInst(opcode) || opcode == spv::Op::OpVariable ||
210+
opcode == spv::Op::OpUntypedVariableKHR ||
210211
opcode == spv::Op::OpUndef) {
211212
module_->AddGlobalValue(std::move(spv_inst));
212213
} else if (spvIsExtendedInstruction(opcode) &&

source/opt/type_manager.cpp

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -374,16 +374,21 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) {
374374
}
375375
case Type::kPointer: {
376376
const Pointer* pointer = type->AsPointer();
377-
uint32_t subtype = GetTypeInstruction(pointer->pointee_type());
378-
if (subtype == 0) {
379-
return 0;
377+
if (pointer->is_untyped()) {
378+
typeInst = MakeUnique<Instruction>(
379+
context(), spv::Op::OpTypeUntypedPointerKHR, 0, id,
380+
std::initializer_list<Operand>{
381+
{SPV_OPERAND_TYPE_STORAGE_CLASS,
382+
{static_cast<uint32_t>(pointer->storage_class())}}});
383+
} else {
384+
uint32_t subtype = GetTypeInstruction(pointer->pointee_type());
385+
typeInst = MakeUnique<Instruction>(
386+
context(), spv::Op::OpTypePointer, 0, id,
387+
std::initializer_list<Operand>{
388+
{SPV_OPERAND_TYPE_STORAGE_CLASS,
389+
{static_cast<uint32_t>(pointer->storage_class())}},
390+
{SPV_OPERAND_TYPE_ID, {subtype}}});
380391
}
381-
typeInst = MakeUnique<Instruction>(
382-
context(), spv::Op::OpTypePointer, 0, id,
383-
std::initializer_list<Operand>{
384-
{SPV_OPERAND_TYPE_STORAGE_CLASS,
385-
{static_cast<uint32_t>(pointer->storage_class())}},
386-
{SPV_OPERAND_TYPE_ID, {subtype}}});
387392
break;
388393
}
389394
case Type::kFunction: {
@@ -680,9 +685,13 @@ Type* TypeManager::RebuildType(uint32_t type_id, const Type& type) {
680685
}
681686
case Type::kPointer: {
682687
const Pointer* pointer_ty = type.AsPointer();
683-
const Type* ele_ty = pointer_ty->pointee_type();
684-
rebuilt_ty = MakeUnique<Pointer>(RebuildType(GetId(ele_ty), *ele_ty),
685-
pointer_ty->storage_class());
688+
if (pointer_ty->pointee_type()) {
689+
const Type* ele_ty = pointer_ty->pointee_type();
690+
rebuilt_ty = MakeUnique<Pointer>(RebuildType(GetId(ele_ty), *ele_ty),
691+
pointer_ty->storage_class());
692+
} else {
693+
rebuilt_ty = MakeUnique<Pointer>(nullptr, pointer_ty->storage_class());
694+
}
686695
break;
687696
}
688697
case Type::kFunction: {
@@ -928,6 +937,11 @@ Type* TypeManager::RecordIfTypeDefinition(const Instruction& inst) {
928937
id_to_incomplete_type_.erase(inst.result_id());
929938

930939
} break;
940+
case spv::Op::OpTypeUntypedPointerKHR: {
941+
type = new Pointer(nullptr, static_cast<spv::StorageClass>(
942+
inst.GetSingleWordInOperand(0)));
943+
id_to_incomplete_type_.erase(inst.result_id());
944+
} break;
931945
case spv::Op::OpTypeFunction: {
932946
bool incomplete_type = false;
933947
uint32_t return_type_id = inst.GetSingleWordInOperand(0);

source/opt/type_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace analysis {
3434

3535
// Hashing functor.
3636
//
37-
// All type pointers must be non-null.
37+
// All type pointers must be non-null to reach here.
3838
struct HashTypePointer {
3939
size_t operator()(const Type* type) const {
4040
assert(type);

source/opt/types.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -621,24 +621,39 @@ bool Pointer::IsSameImpl(const Type* that, IsSameCache* seen) const {
621621
if (!p.second) {
622622
return true;
623623
}
624-
bool same_pointee = pointee_type_->IsSameImpl(pt->pointee_type_, seen);
625-
seen->erase(p.first);
626-
if (!same_pointee) {
627-
return false;
624+
if (pointee_type_ != nullptr && pt->pointee_type_ != nullptr) {
625+
bool same_pointee = pointee_type_->IsSameImpl(pt->pointee_type_, seen);
626+
seen->erase(p.first);
627+
if (!same_pointee) {
628+
return false;
629+
}
630+
} else {
631+
seen->erase(p.first);
632+
// Either both are untyped or it is mixed typed and untyped.
633+
if (pointee_type_ != pt->pointee_type_) {
634+
return false;
635+
}
628636
}
629637
return HasSameDecorations(that);
630638
}
631639

632640
std::string Pointer::str() const {
633641
std::ostringstream os;
634-
os << pointee_type_->str() << " " << static_cast<uint32_t>(storage_class_)
635-
<< "*";
642+
if (pointee_type_) {
643+
os << pointee_type_->str();
644+
} else {
645+
os << "untyped_ptr";
646+
}
647+
os << " " << static_cast<uint32_t>(storage_class_) << "*";
636648
return os.str();
637649
}
638650

639651
size_t Pointer::ComputeExtraStateHash(size_t hash, SeenTypes* seen) const {
640652
hash = hash_combine(hash, uint32_t(storage_class_));
641-
return pointee_type_->ComputeHashValue(hash, seen);
653+
if (pointee_type_) {
654+
hash = pointee_type_->ComputeHashValue(hash, seen);
655+
}
656+
return hash;
642657
}
643658

644659
void Pointer::SetPointeeType(const Type* type) { pointee_type_ = type; }

source/opt/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,8 @@ class Pointer : public Type {
550550
const Type* pointee_type() const { return pointee_type_; }
551551
spv::StorageClass storage_class() const { return storage_class_; }
552552

553+
bool is_untyped() const { return pointee_type_ == nullptr; }
554+
553555
Pointer* AsPointer() override { return this; }
554556
const Pointer* AsPointer() const override { return this; }
555557

test/opt/type_manager_test.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ std::vector<std::unique_ptr<Type>> GenerateAllTypes() {
149149
types.emplace_back(new Pointer(f32, spv::StorageClass::Input));
150150
types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
151151
types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
152+
types.emplace_back(new Pointer(nullptr, spv::StorageClass::Uniform));
152153

153154
// Function
154155
types.emplace_back(new Function(voidt, {}));
@@ -249,6 +250,7 @@ TEST(TypeManager, TypeStrings) {
249250
%cm = OpTypeCooperativeMatrixNV %f64 %id4 %id4 %id4
250251
%id2 = OpConstant %u32 2
251252
%cmkhr = OpTypeCooperativeMatrixKHR %f64 %id4 %id4 %id4 %id2
253+
%untyped = OpTypeUntypedPointerKHR Uniform
252254
)";
253255

254256
std::vector<std::pair<uint32_t, std::string>> type_id_strs = {
@@ -288,10 +290,11 @@ TEST(TypeManager, TypeStrings) {
288290
{38, "[sint32, id(34), words(2,34)]"},
289291
{39, "<float64, 6, 6, 6>"},
290292
{41, "<float64, 6, 6, 6, 40>"},
293+
{42, "untyped_ptr 2*"}, // Include storage class number
291294
};
292295

293296
std::unique_ptr<IRContext> context =
294-
BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text);
297+
BuildModule(SPV_ENV_UNIVERSAL_1_4, nullptr, text);
295298
ASSERT_NE(nullptr, context.get()); // It assembled
296299
TypeManager manager(nullptr, context.get());
297300

test/opt/types_test.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ std::vector<std::unique_ptr<Type>> GenerateAllTypes() {
226226
types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
227227
types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
228228
types.emplace_back(new Pointer(voidt, spv::StorageClass::Function));
229+
types.emplace_back(new Pointer(nullptr, spv::StorageClass::Uniform));
229230

230231
// Function
231232
types.emplace_back(new Function(voidt, {}));
@@ -457,6 +458,15 @@ TEST(Types, RemoveDecorations) {
457458
}
458459
}
459460

461+
TEST(Types, UntypedPointer) {
462+
std::unique_ptr<Type> type(new Pointer(nullptr, spv::StorageClass::Uniform));
463+
const auto untyped = type->AsPointer();
464+
EXPECT_NE(untyped, nullptr);
465+
EXPECT_TRUE(untyped->is_untyped());
466+
EXPECT_EQ(untyped->pointee_type(), nullptr);
467+
EXPECT_EQ(untyped->storage_class(), spv::StorageClass::Uniform);
468+
}
469+
460470
} // namespace
461471
} // namespace analysis
462472
} // namespace opt

0 commit comments

Comments
 (0)