diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp index f64992b53cf2c..c001ef12db98f 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp @@ -386,6 +386,16 @@ void SPIRVEntry::takeAnnotations(SPIRVForward *E) { static_cast(this)->takeExecutionModes(E); } +void SPIRVEntry::replaceTargetIdInDecorates(SPIRVId Id) { + for (auto It = Decorates.begin(), E = Decorates.end(); It != E; ++It) + const_cast(It->second)->setTargetId(Id); + for (auto It = DecorateIds.begin(), E = DecorateIds.end(); It != E; ++It) + const_cast(It->second)->setTargetId(Id); + for (auto It = MemberDecorates.begin(), E = MemberDecorates.end(); It != E; + ++It) + const_cast(It->second)->setTargetId(Id); +} + // Check if an entry has Kind of decoration and get the literal of the // first decoration of such kind at Index. bool SPIRVEntry::hasDecorate(Decoration Kind, size_t Index, diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h index 743c8becd533b..fe3c071b3d299 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h @@ -371,6 +371,7 @@ class SPIRVEntry { void takeDecorates(SPIRVEntry *); void takeDecorateIds(SPIRVEntry *); void takeMemberDecorates(SPIRVEntry *); + void replaceTargetIdInDecorates(SPIRVId); /// After a SPIRV entry is created during reading SPIRV binary by default /// constructor, this function is called to allow the SPIRV entry to resize diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp index fffccd40f417f..4195a598a9236 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp @@ -1176,17 +1176,19 @@ SPIRVEntry *SPIRVModuleImpl::replaceForward(SPIRVForward *Forward, SPIRVEntry *Entry) { SPIRVId Id = Entry->getId(); SPIRVId ForwardId = Forward->getId(); - if (ForwardId == Id) + if (ForwardId == Id) { IdEntryMap[Id] = Entry; - else { + // Annotations include name, decorations, execution modes + Entry->takeAnnotations(Forward); + } else { auto Loc = IdEntryMap.find(Id); assert(Loc != IdEntryMap.end()); IdEntryMap.erase(Loc); Entry->setId(ForwardId); IdEntryMap[ForwardId] = Entry; + // Replace current Id with ForwardId in decorates. + Entry->replaceTargetIdInDecorates(ForwardId); } - // Annotations include name, decorations, execution modes - Entry->takeAnnotations(Forward); delete Forward; return Entry; } diff --git a/llvm-spirv/test/transcoding/decoration-forward-decl.ll b/llvm-spirv/test/transcoding/decoration-forward-decl.ll new file mode 100644 index 0000000000000..96cb47b99a004 --- /dev/null +++ b/llvm-spirv/test/transcoding/decoration-forward-decl.ll @@ -0,0 +1,39 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: spirv-val %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; Check saturation conversion is translated when there is forward declaration +; of SPIRV entry. + +; CHECK-SPIRV: Decorate [[SAT:[0-9]+]] SaturatedConversion +; CHECK-SPIRV: ConvertFToU {{[0-9]+}} [[SAT]] + +; CHECK-LLVM: convert_uchar_satf + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1" +target triple = "spir64" + +declare spir_func zeroext i8 @_Z30__spirv_ConvertFToU_Ruchar_satf(float) + +define spir_func void @forward(float %val, ptr addrspace(1) %dst) { +entry: + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %new_val.0 = phi i8 [ undef, %entry ], [ %call1, %for.body ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %cmp = icmp ult i32 %i.0, 1 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %call1 = call spir_func zeroext i8 @_Z30__spirv_ConvertFToU_Ruchar_satf(float noundef %val) + %inc = add i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + store i8 %new_val.0, ptr addrspace(1) %dst, align 1 + ret void +}