Skip to content

Commit ee0eea2

Browse files
jcranmer-inteldbudanov-cmplr
authored andcommitted
Fix type scavenger for variable arguments and multiple-uses-of-types cases. (#1606)
Original commit: KhronosGroup/SPIRV-LLVM-Translator@401d124
1 parent 2165452 commit ee0eea2

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

llvm-spirv/lib/SPIRV/SPIRVTypeScavenger.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,14 @@ void SPIRVTypeScavenger::correctUseTypes(Instruction &I) {
430430
// arguments we pass in to the argument requirements of the function.
431431
if (Function *F = CB->getCalledFunction()) {
432432
for (Use &U : CB->args()) {
433+
// If we're calling a var-arg method, we have more operands than the
434+
// function has parameters. Bail out if we hit that point.
435+
unsigned ArgNo = CB->getArgOperandNo(&U);
436+
if (ArgNo >= F->arg_size())
437+
break;
433438
if (U->getType()->isPointerTy())
434439
PointerOperands.emplace_back(
435-
U.getOperandNo(),
436-
computePointerElementType(F->getArg(CB->getArgOperandNo(&U))));
440+
U.getOperandNo(), computePointerElementType(F->getArg(ArgNo)));
437441
}
438442
}
439443
}
@@ -475,6 +479,16 @@ void SPIRVTypeScavenger::correctUseTypes(Instruction &I) {
475479
U.set(CastedValue);
476480
};
477481

482+
// This handles the scenario where a deferred type gets resolved to a fixed
483+
// type during handling of this instruction, and another operand is using
484+
// the same deferred type later in the instruction.
485+
auto ReplaceTypeInOperands = [&](DeducedType From, DeducedType To) {
486+
for (auto &ReplacePair : PointerOperands) {
487+
if (ReplacePair.second == From)
488+
ReplacePair.second = To;
489+
}
490+
};
491+
478492
if (isa<Value *>(UsedTy)) {
479493
// When the use is of an indirect-pointer type, insert a bitcast to the
480494
// use type only for this use. This prevents indirect pointers from
@@ -491,15 +505,18 @@ void SPIRVTypeScavenger::correctUseTypes(Instruction &I) {
491505
// Source type is fixed, use type is deferred: set the deferred type to
492506
// the fixed type.
493507
fixType(*DeferredUseTy, FixedTy);
508+
ReplaceTypeInOperands(DeferredUseTy, FixedTy);
494509
}
495510
} else if (auto *DeferredTy = dyn_cast<DeferredType *>(SourceTy)) {
496511
if (auto *FixedUseTy = dyn_cast<Type *>(UsedTy)) {
497512
// Source type is fixed, use type is deferred: set the deferred type to
498513
// the fixed type.
499514
fixType(*DeferredTy, FixedUseTy);
515+
ReplaceTypeInOperands(DeferredTy, FixedUseTy);
500516
} else if (auto *DeferredUseTy = dyn_cast<DeferredType *>(UsedTy)) {
501517
// If they're both deferred, merge the two types together.
502518
mergeType(DeferredTy, DeferredUseTy);
519+
ReplaceTypeInOperands(DeferredUseTy, DeferredTy);
503520
}
504521
}
505522
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s
3+
; RUN: llvm-spirv %t.bc -o %t.spv
4+
; RUN: spirv-val %t.spv
5+
6+
; This test checks that, when we fix a deferred type to a known value in the
7+
; type scavenger, we correctly also handle replacing other types that are used
8+
; in the same instruction.
9+
10+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
11+
target triple = "spir-unknown-unknown"
12+
13+
; CHECK: 4 TypeInt [[INT:[0-9]+]] 32 0
14+
; CHECK: 4 TypePointer [[INTPTR:[0-9]+]] 7 [[INT]]
15+
16+
; Function Attrs: nounwind
17+
define spir_kernel void @foo() {
18+
; CHECK: 4 Variable [[INTPTR]] [[IPTR:[0-9]+]] 7
19+
; CHECK: 4 Bitcast [[INTPTR]] [[UPTR:[0-9]+]] [[IPTR]]
20+
; CHECK: 4 Bitcast [[INTPTR]] [[UPTR2:[0-9]+]] [[IPTR]]
21+
entry:
22+
%iptr = alloca i32, align 4
23+
%uptr = bitcast ptr %iptr to ptr
24+
%uptr2 = bitcast ptr %iptr to ptr
25+
br i1 false, label %a, label %b
26+
27+
a:
28+
; CHECK: 2 Label [[A:[0-9]+]]
29+
br i1 false, label %c, label %d
30+
31+
b:
32+
; CHECK: 2 Label [[B:[0-9]+]]
33+
br label %block
34+
35+
c:
36+
; CHECK: 2 Label [[C:[0-9]+]]
37+
br label %block
38+
39+
d:
40+
; CHECK: 2 Label [[D:[0-9]+]]
41+
br label %block
42+
43+
block:
44+
; CHECK: 9 Phi [[INTPTR]] {{[0-9]+}} [[UPTR]] [[B]] [[IPTR]] [[C]] [[UPTR2]] [[D]]
45+
%val = phi ptr [ %uptr, %b ], [ %iptr, %c ], [ %uptr2, %d ]
46+
ret void
47+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s
3+
; RUN: llvm-spirv %t.bc -o %t.spv
4+
5+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
6+
target triple = "spir-unknown-unknown"
7+
8+
@.str = internal unnamed_addr addrspace(2) constant [11 x i8] c"Value: %p\0A\00", align 1
9+
10+
11+
; CHECK: 4 TypeInt [[INT:[0-9]+]] 32 0
12+
; CHECK: 4 TypePointer [[INTPTR:[0-9]+]] 7 [[INT]]
13+
; CHECK: 5 Variable {{[0-9]+}} [[STR:[0-9]+]] 0
14+
; CHECK: 4 Variable [[INTPTR]] [[IPTR:[0-9]+]] 7
15+
; CHECK: 7 ExtInst [[INT]] {{[0-9]+}} {{[0-9]+}} printf [[STR]] [[IPTR]]
16+
17+
; Function Attrs: nounwind
18+
define spir_kernel void @foo() {
19+
%iptr = alloca i32, align 4
20+
%res = call spir_func i32 (ptr addrspace(2), ...) @_Z18__spirv_ocl_printfPU3AS2c(ptr addrspace(2) @.str, ptr %iptr)
21+
ret void
22+
}
23+
24+
declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS2c(ptr addrspace(2), ...)

0 commit comments

Comments
 (0)