Skip to content

Commit

Permalink
Handle circular dependencies between structs
Browse files Browse the repository at this point in the history
---------------------------
  • Loading branch information
mshelego authored and sys-cmllvm committed Mar 10, 2023
1 parent 721a39c commit eceefb6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
28 changes: 24 additions & 4 deletions GenXIntrinsics/lib/GenXIntrinsics/GenXSingleElementVectorUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,43 @@ static Type *getTypeFreeFromSingleElementVector(Type *T) {
if (VCINTR::VectorType::getNumElements(VecTy) == 1)
return VecTy->getElementType();
} else if (auto *StructTy = dyn_cast<StructType>(T)) {
// If there is a key for this struct type is in SEV-Free to SEV-Rich map it
// means that the type is already SEV-Free
if (SEVRichStructMap.find(StructTy) != SEVRichStructMap.end())
return T;
auto It = SEVFreeStructMap.find(StructTy);
if (It != SEVFreeStructMap.end())
return It->second;
// To handle circle dependencies we create opaque struct type and add it to
// the map. If this struct or any nested one contains a pointer to the type
// we are rewriting it will be automatically changed to this incomplete type
// and traversing will stop
StructType *NewStructTy = StructType::create(T->getContext());
It = SEVFreeStructMap.insert(std::make_pair(StructTy, NewStructTy)).first;
bool HasSEV = false;
std::vector<Type *> NewElements;
for (auto *ElemTy : StructTy->elements()) {
Type *NewElemTy = getTypeFreeFromSingleElementVector(ElemTy);
if (NewElemTy != ElemTy)
HasSEV = true;
NewElements.push_back(NewElemTy);
if (!HasSEV && NewElemTy != ElemTy) {
// If new type is not equal to the old one it doesn't always mean that
// there is a SEV element in the struct. It could be also temporary
// unfininished (opaque) struct type or a pointer to it
auto *TempTy = NewElemTy;
while (auto *Ptr = dyn_cast<PointerType>(TempTy))
TempTy = VCINTR::Type::getNonOpaquePtrEltTy(Ptr);
if (auto *NestedStructTy = dyn_cast<StructType>(TempTy))
HasSEV = !NestedStructTy->isOpaque();
else
HasSEV = true;
}
}
if (HasSEV) {
StructType *NewStructTy = StructType::create(NewElements);
SEVFreeStructMap.insert(std::make_pair(StructTy, NewStructTy));
NewStructTy->setBody(NewElements);
SEVRichStructMap.insert(std::make_pair(NewStructTy, StructTy));
return NewStructTy;
}
SEVFreeStructMap.erase(It);
}
return T;
}
Expand Down
8 changes: 6 additions & 2 deletions GenXIntrinsics/test/Adaptors/sev_struct.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ target triple = "spir64"

; CHECK: [[STRUCT1:[^ ]+]] = type { i32, <2 x i32>, [[STRUCT2:[^ ]+]] }
%struct.sev_test = type { <1 x i32>, <2 x i32>, %struct.sev_test_nested }
; CHECK: [[STRUCT2]] = type { i32*, <2 x i32>* }
%struct.sev_test_nested = type { <1 x i32>*, <2 x i32>* }
; CHECK: [[STRUCT2]] = type { i32*, <2 x i32>*, [[STRUCT1]]* }
%struct.sev_test_nested = type { <1 x i32>*, <2 x i32>*, %struct.sev_test* }

; CHECK: define void @test(i32 "VCSingleElementVector"="0" %sev, i32* "VCSingleElementVector"="0" %sev_ptr)
define void @test(<1 x i32> %sev, <1 x i32>* %sev_ptr) {
Expand All @@ -30,5 +30,9 @@ define void @test(<1 x i32> %sev, <1 x i32>* %sev_ptr) {
%4 = getelementptr inbounds %struct.sev_test_nested, %struct.sev_test_nested* %3, i32 0, i32 0
; CHECK: store i32* %sev_ptr, i32** %4, align 8
store <1 x i32>* %sev_ptr, <1 x i32>** %4, align 8
; CHECK: %5 = getelementptr inbounds [[STRUCT2]], [[STRUCT2]]* %3, i32 0, i32 2
%5 = getelementptr inbounds %struct.sev_test_nested, %struct.sev_test_nested* %3, i32 0, i32 2
; CHECK: store [[STRUCT1]]* %1, [[STRUCT1]]** %5, align 8
store %struct.sev_test* %1, %struct.sev_test** %5, align 8
ret void
}

0 comments on commit eceefb6

Please sign in to comment.