Skip to content

Commit aaf82ea

Browse files
jcranmer-intelFznamznon
authored andcommitted
Translate constant global variable references correctly in opaque pointer mode. (#1666)
Original commit: KhronosGroup/SPIRV-LLVM-Translator@81464b0
1 parent f277bee commit aaf82ea

File tree

3 files changed

+87
-7
lines changed

3 files changed

+87
-7
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,32 @@ void LLVMToSPIRVBase::transFPGAFunctionMetadata(SPIRVFunction *BF,
10491049
}
10501050
}
10511051

1052+
SPIRVValue *LLVMToSPIRVBase::transConstantUse(Constant *C) {
1053+
// Constant expressions expect their pointer types to be i8* in opaque pointer
1054+
// mode, but the value may have a different "natural" type. If that is the
1055+
// case, we need to adjust the type of the constant.
1056+
SPIRVValue *Trans = transValue(C, nullptr, true, FuncTransMode::Pointer);
1057+
SPIRVType *ExpectedType = transType(C->getType());
1058+
if (Trans->getType() == ExpectedType || Trans->getType()->isTypePipeStorage())
1059+
return Trans;
1060+
1061+
assert(C->getType()->isPointerTy() &&
1062+
"Only pointer type mismatches should be possible");
1063+
// In the common case of strings ([N x i8] GVs), see if we can emit a GEP
1064+
// instruction.
1065+
if (auto *GV = dyn_cast<GlobalVariable>(C)) {
1066+
if (GV->getValueType()->isArrayTy() &&
1067+
GV->getValueType()->getArrayElementType()->isIntegerTy(8)) {
1068+
SPIRVValue *Offset = transValue(getUInt32(M, 0), nullptr);
1069+
return BM->addPtrAccessChainInst(ExpectedType, Trans, {Offset, Offset},
1070+
nullptr, true);
1071+
}
1072+
}
1073+
1074+
// Otherwise, just use a bitcast.
1075+
return BM->addUnaryInst(OpBitcast, ExpectedType, Trans, nullptr);
1076+
}
1077+
10521078
SPIRVValue *LLVMToSPIRVBase::transConstant(Value *V) {
10531079
if (auto CPNull = dyn_cast<ConstantPointerNull>(V))
10541080
return BM->addNullConstant(
@@ -1085,30 +1111,28 @@ SPIRVValue *LLVMToSPIRVBase::transConstant(Value *V) {
10851111
if (auto ConstDA = dyn_cast<ConstantDataArray>(V)) {
10861112
std::vector<SPIRVValue *> BV;
10871113
for (unsigned I = 0, E = ConstDA->getNumElements(); I != E; ++I)
1088-
BV.push_back(transValue(ConstDA->getElementAsConstant(I), nullptr, true,
1089-
FuncTransMode::Pointer));
1114+
BV.push_back(transConstantUse(ConstDA->getElementAsConstant(I)));
10901115
return BM->addCompositeConstant(transType(V->getType()), BV);
10911116
}
10921117

10931118
if (auto ConstA = dyn_cast<ConstantArray>(V)) {
10941119
std::vector<SPIRVValue *> BV;
10951120
for (auto I = ConstA->op_begin(), E = ConstA->op_end(); I != E; ++I)
1096-
BV.push_back(transValue(*I, nullptr, true, FuncTransMode::Pointer));
1121+
BV.push_back(transConstantUse(cast<Constant>(*I)));
10971122
return BM->addCompositeConstant(transType(V->getType()), BV);
10981123
}
10991124

11001125
if (auto ConstDV = dyn_cast<ConstantDataVector>(V)) {
11011126
std::vector<SPIRVValue *> BV;
11021127
for (unsigned I = 0, E = ConstDV->getNumElements(); I != E; ++I)
1103-
BV.push_back(transValue(ConstDV->getElementAsConstant(I), nullptr, true,
1104-
FuncTransMode::Pointer));
1128+
BV.push_back(transConstantUse(ConstDV->getElementAsConstant(I)));
11051129
return BM->addCompositeConstant(transType(V->getType()), BV);
11061130
}
11071131

11081132
if (auto ConstV = dyn_cast<ConstantVector>(V)) {
11091133
std::vector<SPIRVValue *> BV;
11101134
for (auto I = ConstV->op_begin(), E = ConstV->op_end(); I != E; ++I)
1111-
BV.push_back(transValue(*I, nullptr, true, FuncTransMode::Pointer));
1135+
BV.push_back(transConstantUse(cast<Constant>(*I)));
11121136
return BM->addCompositeConstant(transType(V->getType()), BV);
11131137
}
11141138

@@ -1148,7 +1172,7 @@ SPIRVValue *LLVMToSPIRVBase::transConstant(Value *V) {
11481172
}
11491173
std::vector<SPIRVValue *> BV;
11501174
for (auto I = ConstV->op_begin(), E = ConstV->op_end(); I != E; ++I)
1151-
BV.push_back(transValue(*I, nullptr, true, FuncTransMode::Pointer));
1175+
BV.push_back(transConstantUse(cast<Constant>(*I)));
11521176
return BM->addCompositeConstant(transType(V->getType()), BV);
11531177
}
11541178

llvm-spirv/lib/SPIRV/SPIRVWriter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ class LLVMToSPIRVBase {
130130
bool transExecutionMode();
131131
void transFPContract();
132132
SPIRVValue *transConstant(Value *V);
133+
/// Translate a reference to a constant in a constant expression. This may
134+
/// involve inserting extra bitcasts to correct type issues.
135+
SPIRVValue *transConstantUse(Constant *V);
133136
SPIRVValue *transValue(Value *V, SPIRVBasicBlock *BB,
134137
bool CreateForward = true,
135138
FuncTransMode FuncTrans = FuncTransMode::Decl);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; Check that we can handle constant expressions correctly.
2+
; RUN: llvm-as %s -o %t.bc
3+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
4+
; RUN: llvm-spirv %t.bc -o %t.spv
5+
; RUN: spirv-val %t.spv
6+
; RUN: llvm-spirv -r %t.spv -emit-opaque-pointers -o %t.rev.bc
7+
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
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"
10+
target triple = "spir-unknown-unknown"
11+
12+
; CHECK-SPIRV-DAG: 4 TypeInt [[U8:[0-9]+]] 8 0
13+
; CHECK-SPIRV-DAG: 4 TypeInt [[U32:[0-9]+]] 32 0
14+
; CHECK-SPIRV-DAG: 4 TypeInt [[U64:[0-9]+]] 64 0
15+
; CHECK-SPIRV-DAG: 4 Constant [[U32]] [[I320:[0-9]+]] 0
16+
; CHECK-SPIRV-DAG: 4 Constant [[U32]] [[I323:[0-9]+]] 3
17+
; CHECK-SPIRV: 4 TypePointer [[AS2:[0-9]+]] 0 [[U8]]
18+
; CHECK-SPIRV: 4 TypePointer [[AS1:[0-9]+]] 5 [[U8]]
19+
; CHECK-SPIRV-DAG: 4 TypeStruct [[STRUCTTY:[0-9]+]]
20+
; CHECK-SPIRV-DAG: 4 TypeArray [[ARRAYTY:[0-9]+]] [[AS1]] [[I323]]
21+
22+
@astr = internal addrspace(2) constant [7 x i8] c"string\00", align 4
23+
; CHECK-SPIRV: 5 Variable {{[0-9]+}} [[ASTR:[0-9]+]] 0
24+
25+
@i64arr = addrspace(1) constant [3 x i64] [i64 0, i64 1, i64 2]
26+
; CHECK-SPIRV: 5 Variable {{[0-9]+}} [[I64ARR:[0-9]+]] 5
27+
28+
@struct = addrspace(1) global {ptr addrspace(2), ptr addrspace(1)} { ptr addrspace(2) @astr, ptr addrspace(1) @i64arr }
29+
30+
; CHECK-SPIRV: 7 SpecConstantOp [[AS2]] [[ASTRC:[0-9]+]] 70 [[ASTR]] [[I320]] [[I320]]
31+
; CHECK-SPIRV: 5 SpecConstantOp [[AS1]] [[I64ARRC:[0-9]+]] 124 [[I64ARR]]
32+
; CHECK-SPIRV: 5 ConstantComposite [[STRUCTTY]] [[STRUCT_INIT:[0-9]+]] [[ASTRC]] [[I64ARRC]]
33+
; CHECK-SPIRV: 5 Variable {{[0-9]+}} [[STRUCT:[0-9]+]] 5 [[STRUCT_INIT]]
34+
35+
@array = addrspace(1) global [3 x ptr addrspace(1)] [ptr addrspace(1) @i64arr, ptr addrspace(1) @struct, ptr addrspace(1) getelementptr ([3 x i64], ptr addrspace(1) @i64arr, i64 0, i64 1) ]
36+
37+
; CHECK-SPIRV: 5 SpecConstantOp [[AS1]] [[I64ARRC2:[0-9]+]] 124 [[I64ARR]]
38+
; CHECK-SPIRV: 5 SpecConstantOp [[AS1]] [[STRUCTC:[0-9]+]] 124 [[STRUCT]]
39+
; CHECK-SPIRV: 7 SpecConstantOp {{[0-9]+}} [[GEP:[0-9]+]] 70 [[I64ARR]]
40+
; CHECK-SPIRV: 5 SpecConstantOp [[AS1]] [[I64ARRC3:[0-9]+]] 124 [[GEP]]
41+
; CHECK-SPIRV: 6 ConstantComposite [[ARRAYTY]] [[ARRAY_INIT:[0-9]+]] [[I64ARRC2]] [[STRUCTC]] [[I64ARRC3]]
42+
; CHECK-SPIRV: 5 Variable {{[0-9]+}} [[ARRAY:[0-9]+]] 5 [[ARRAY_INIT]]
43+
44+
; CHECK-LLVM: %structtype = type { ptr addrspace(2), ptr addrspace(1) }
45+
; CHECK-LLVM: @astr = internal unnamed_addr addrspace(2) constant [7 x i8] c"string\00", align 4
46+
; CHECK-LLVM: @i64arr = addrspace(1) constant [3 x i64] [i64 0, i64 1, i64 2]
47+
; CHECK-LLVM: @struct = addrspace(1) global %structtype { ptr addrspace(2) @astr, ptr addrspace(1) @i64arr }
48+
; CHECK-LLVM: @array = addrspace(1) global [3 x ptr addrspace(1)] [ptr addrspace(1) @i64arr, ptr addrspace(1) @struct, ptr addrspace(1) getelementptr inbounds ([3 x i64], ptr addrspace(1) @i64arr, i64 0, i64 1)]
49+
50+
define spir_kernel void @foo() {
51+
%val = load i32, ptr addrspace(2) @astr, align 4
52+
ret void
53+
}

0 commit comments

Comments
 (0)