Skip to content

Commit 0164438

Browse files
zuban32vladimirlaz
authored andcommitted
Support lowering of constant expressions vector
Since the translator has to lower LLVM constant expressions to be able to represent them in SPIR-V, we now need to support not only single constexprs but vectors of constexprs as well.
1 parent 835734c commit 0164438

File tree

2 files changed

+157
-22
lines changed

2 files changed

+157
-22
lines changed

llvm-spirv/lib/SPIRV/SPIRVLowerConstExpr.cpp

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -123,31 +123,51 @@ void SPIRVLowerConstExpr::visit(Module *M) {
123123
auto FBegin = I.begin();
124124
while (!WorkList.empty()) {
125125
auto II = WorkList.front();
126-
WorkList.pop_front();
127-
for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) {
128-
auto Op = II->getOperand(OI);
129126

130-
if (auto CE = dyn_cast<ConstantExpr>(Op)) {
131-
SPIRVDBG(dbgs() << "[lowerConstantExpressions] " << *CE;)
132-
auto ReplInst = CE->getAsInstruction();
133-
auto InsPoint = II->getParent() == &*FBegin ? II : &FBegin->back();
134-
ReplInst->insertBefore(InsPoint);
135-
SPIRVDBG(dbgs() << " -> " << *ReplInst << '\n';)
136-
WorkList.push_front(ReplInst);
137-
std::vector<Instruction *> Users;
138-
// Do not replace use during iteration of use. Do it in another loop
139-
for (auto U : CE->users()) {
140-
SPIRVDBG(dbgs()
141-
<< "[lowerConstantExpressions] Use: " << *U << '\n';)
142-
if (auto InstUser = dyn_cast<Instruction>(U)) {
143-
// Only replace users in scope of current function
144-
if (InstUser->getParent()->getParent() == &I)
145-
Users.push_back(InstUser);
146-
}
127+
auto LowerOp = [&II, &FBegin, &I](ConstantExpr *CE) {
128+
SPIRVDBG(dbgs() << "[lowerConstantExpressions] " << *CE;)
129+
auto ReplInst = CE->getAsInstruction();
130+
auto InsPoint = II->getParent() == &*FBegin ? II : &FBegin->back();
131+
ReplInst->insertBefore(InsPoint);
132+
SPIRVDBG(dbgs() << " -> " << *ReplInst << '\n';)
133+
std::vector<Instruction *> Users;
134+
// Do not replace use during iteration of use. Do it in another loop
135+
for (auto U : CE->users()) {
136+
SPIRVDBG(dbgs() << "[lowerConstantExpressions] Use: " << *U << '\n';)
137+
if (auto InstUser = dyn_cast<Instruction>(U)) {
138+
// Only replace users in scope of current function
139+
if (InstUser->getParent()->getParent() == &I)
140+
Users.push_back(InstUser);
147141
}
148-
for (auto &User : Users)
149-
User->replaceUsesOfWith(CE, ReplInst);
150142
}
143+
for (auto &User : Users)
144+
User->replaceUsesOfWith(CE, ReplInst);
145+
return ReplInst;
146+
};
147+
148+
WorkList.pop_front();
149+
for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) {
150+
auto Op = II->getOperand(OI);
151+
auto *Vec = dyn_cast<ConstantVector>(Op);
152+
if (Vec && std::all_of(Vec->op_begin(), Vec->op_end(),
153+
[](Value *V) { return isa<ConstantExpr>(V); })) {
154+
// Expand a vector of constexprs and construct it back with series of
155+
// insertelement instructions
156+
std::list<Instruction *> ReplList;
157+
std::transform(
158+
Vec->op_begin(), Vec->op_end(), std::back_inserter(ReplList),
159+
[LowerOp](Value *V) { return LowerOp(cast<ConstantExpr>(V)); });
160+
Value *Repl = nullptr;
161+
unsigned Idx = 0;
162+
for (auto V : ReplList)
163+
Repl = InsertElementInst::Create(
164+
(Repl ? Repl : UndefValue::get(Vec->getType())), V,
165+
ConstantInt::get(Type::getInt32Ty(M->getContext()), Idx++), "",
166+
II);
167+
II->replaceUsesOfWith(Op, Repl);
168+
WorkList.splice(WorkList.begin(), ReplList);
169+
} else if (auto CE = dyn_cast<ConstantExpr>(Op))
170+
WorkList.push_front(LowerOp(CE));
151171
}
152172
}
153173
}

llvm-spirv/test/constexpr_vector.ll

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
; RUN: llvm-as < %s | llvm-spirv -s | llvm-dis | FileCheck %s --check-prefix=CHECK-LLVM
2+
3+
; CHECK-LLVM: define dllexport void @vadd() {
4+
; CHECK-LLVM-NEXT: entry:
5+
; CHECK-LLVM-NEXT: %Funcs = alloca <16 x i8>, align 16
6+
; CHECK-LLVM-NEXT: %0 = ptrtoint i32 (i32)* @_Z2f1u2CMvb32_j to i64
7+
; CHECK-LLVM-NEXT: %1 = bitcast i64 %0 to <8 x i8>
8+
; CHECK-LLVM-NEXT: %2 = extractelement <8 x i8> %1, i32 0
9+
; CHECK-LLVM-NEXT: %3 = extractelement <8 x i8> %1, i32 1
10+
; CHECK-LLVM-NEXT: %4 = extractelement <8 x i8> %1, i32 2
11+
; CHECK-LLVM-NEXT: %5 = extractelement <8 x i8> %1, i32 3
12+
; CHECK-LLVM-NEXT: %6 = extractelement <8 x i8> %1, i32 4
13+
; CHECK-LLVM-NEXT: %7 = extractelement <8 x i8> %1, i32 5
14+
; CHECK-LLVM-NEXT: %8 = extractelement <8 x i8> %1, i32 6
15+
; CHECK-LLVM-NEXT: %9 = extractelement <8 x i8> %1, i32 7
16+
; CHECK-LLVM-NEXT: %10 = ptrtoint i32 (i32)* @_Z2f2u2CMvb32_j to i64
17+
; CHECK-LLVM-NEXT: %11 = bitcast i64 %10 to <8 x i8>
18+
; CHECK-LLVM-NEXT: %12 = extractelement <8 x i8> %11, i32 0
19+
; CHECK-LLVM-NEXT: %13 = extractelement <8 x i8> %11, i32 1
20+
; CHECK-LLVM-NEXT: %14 = extractelement <8 x i8> %11, i32 2
21+
; CHECK-LLVM-NEXT: %15 = extractelement <8 x i8> %11, i32 3
22+
; CHECK-LLVM-NEXT: %16 = extractelement <8 x i8> %11, i32 4
23+
; CHECK-LLVM-NEXT: %17 = extractelement <8 x i8> %11, i32 5
24+
; CHECK-LLVM-NEXT: %18 = extractelement <8 x i8> %11, i32 6
25+
; CHECK-LLVM-NEXT: %19 = extractelement <8 x i8> %11, i32 7
26+
; CHECK-LLVM-NEXT: %20 = insertelement <16 x i8> undef, i8 %2, i32 0
27+
; CHECK-LLVM-NEXT: %21 = insertelement <16 x i8> %20, i8 %3, i32 1
28+
; CHECK-LLVM-NEXT: %22 = insertelement <16 x i8> %21, i8 %4, i32 2
29+
; CHECK-LLVM-NEXT: %23 = insertelement <16 x i8> %22, i8 %5, i32 3
30+
; CHECK-LLVM-NEXT: %24 = insertelement <16 x i8> %23, i8 %6, i32 4
31+
; CHECK-LLVM-NEXT: %25 = insertelement <16 x i8> %24, i8 %7, i32 5
32+
; CHECK-LLVM-NEXT: %26 = insertelement <16 x i8> %25, i8 %8, i32 6
33+
; CHECK-LLVM-NEXT: %27 = insertelement <16 x i8> %26, i8 %9, i32 7
34+
; CHECK-LLVM-NEXT: %28 = insertelement <16 x i8> %27, i8 %12, i32 8
35+
; CHECK-LLVM-NEXT: %29 = insertelement <16 x i8> %28, i8 %13, i32 9
36+
; CHECK-LLVM-NEXT: %30 = insertelement <16 x i8> %29, i8 %14, i32 10
37+
; CHECK-LLVM-NEXT: %31 = insertelement <16 x i8> %30, i8 %15, i32 11
38+
; CHECK-LLVM-NEXT: %32 = insertelement <16 x i8> %31, i8 %16, i32 12
39+
; CHECK-LLVM-NEXT: %33 = insertelement <16 x i8> %32, i8 %17, i32 13
40+
; CHECK-LLVM-NEXT: %34 = insertelement <16 x i8> %33, i8 %18, i32 14
41+
; CHECK-LLVM-NEXT: %35 = insertelement <16 x i8> %34, i8 %19, i32 15
42+
; CHECK-LLVM-NEXT: store <16 x i8> %35, <16 x i8>* %Funcs, align 16
43+
; CHECK-LLVM-NEXT: ret void
44+
; CHECK-LLVM-NEXT: }
45+
46+
; RUN: llvm-as < %s | llvm-spirv -spirv-text | FileCheck %s --check-prefix=CHECK-SPIRV
47+
48+
; CHECK-SPIRV: 4 Name [[Funcs:[0-9]+]] "Funcs"
49+
50+
; CHECK-SPIRV-DAG: 4 TypeInt [[TypeInt8:[0-9]+]] 8 0
51+
; CHECK-SPIRV-DAG: 4 TypeInt [[TypeInt32:[0-9]+]] 32 0
52+
; CHECK-SPIRV-DAG: 4 TypeInt [[TypeInt64:[0-9]+]] 64 0
53+
; CHECK-SPIRV-DAG: 4 TypeVector [[TypeVec16:[0-9]+]] [[TypeInt8]] 16
54+
; CHECK-SPIRV-DAG: 4 TypeVector [[TypeVec8:[0-9]+]] [[TypeInt8]] 8
55+
; CHECK-SPIRV-DAG: 4 TypePointer [[StorePtr:[0-9]+]] 7 [[TypeVec16]]
56+
; CHECK-SPIRV-DAG: 3 Undef [[TypeVec16]] [[TypeUndef:[0-9]+]]
57+
58+
; CHECK-SPIRV: 4 ConvertPtrToU [[TypeInt64]] [[Ptr1:[0-9]+]] {{[0-9]+}}
59+
; CHECK-SPIRV-NEXT: 4 Bitcast [[TypeVec8]] [[Vec1:[0-9]+]] [[Ptr1]]
60+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v00:[0-9]+]] [[Vec1]] 0
61+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v01:[0-9]+]] [[Vec1]] 1
62+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v02:[0-9]+]] [[Vec1]] 2
63+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v03:[0-9]+]] [[Vec1]] 3
64+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v04:[0-9]+]] [[Vec1]] 4
65+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v05:[0-9]+]] [[Vec1]] 5
66+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v06:[0-9]+]] [[Vec1]] 6
67+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v07:[0-9]+]] [[Vec1]] 7
68+
; CHECK-SPIRV-NEXT: 4 ConvertPtrToU [[TypeInt64]] [[Ptr2:[0-9]+]] {{[0-9]+}}
69+
; CHECK-SPIRV-NEXT: 4 Bitcast [[TypeVec8]] [[Vec2:[0-9]+]] [[Ptr2]]
70+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v10:[0-9]+]] [[Vec2]] 0
71+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v11:[0-9]+]] [[Vec2]] 1
72+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v12:[0-9]+]] [[Vec2]] 2
73+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v13:[0-9]+]] [[Vec2]] 3
74+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v14:[0-9]+]] [[Vec2]] 4
75+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v15:[0-9]+]] [[Vec2]] 5
76+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v16:[0-9]+]] [[Vec2]] 6
77+
; CHECK-SPIRV-NEXT: 5 CompositeExtract [[TypeInt8]] [[v17:[0-9]+]] [[Vec2]] 7
78+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec0:[0-9]+]] [[v00]] [[TypeUndef]] 0
79+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec1:[0-9]+]] [[v01]] [[NewVec0]] 1
80+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec2:[0-9]+]] [[v02]] [[NewVec1]] 2
81+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec3:[0-9]+]] [[v03]] [[NewVec2]] 3
82+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec4:[0-9]+]] [[v04]] [[NewVec3]] 4
83+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec5:[0-9]+]] [[v05]] [[NewVec4]] 5
84+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec6:[0-9]+]] [[v06]] [[NewVec5]] 6
85+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec7:[0-9]+]] [[v07]] [[NewVec6]] 7
86+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec8:[0-9]+]] [[v10]] [[NewVec7]] 8
87+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec9:[0-9]+]] [[v11]] [[NewVec8]] 9
88+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec10:[0-9]+]] [[v12]] [[NewVec9]] 10
89+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec11:[0-9]+]] [[v13]] [[NewVec10]] 11
90+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec12:[0-9]+]] [[v14]] [[NewVec11]] 12
91+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec13:[0-9]+]] [[v15]] [[NewVec12]] 13
92+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec14:[0-9]+]] [[v16]] [[NewVec13]] 14
93+
; CHECK-SPIRV-NEXT: 6 CompositeInsert [[TypeVec16]] [[NewVec15:[0-9]+]] [[v17]] [[NewVec14]] 15
94+
; CHECK-SPIRV-NEXT: 5 Store [[Funcs]] [[NewVec15]] [[TypeInt32]] [[StorePtr]]
95+
96+
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"
97+
target triple = "spir-unknown-unknown"
98+
99+
; Function Attrs: noinline norecurse nounwind readnone
100+
define internal i32 @_Z2f1u2CMvb32_j(i32 %x) {
101+
entry:
102+
ret i32 %x
103+
}
104+
; Function Attrs: noinline norecurse nounwind readnone
105+
define internal i32 @_Z2f2u2CMvb32_j(i32 %x) {
106+
entry:
107+
ret i32 %x
108+
}
109+
; Function Attrs: noinline nounwind
110+
define dllexport void @vadd() {
111+
entry:
112+
%Funcs = alloca <16 x i8>, align 16
113+
store <16 x i8> <i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 0), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 1), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 2), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 3), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 4), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 5), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 6), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f1u2CMvb32_j to i64) to <8 x i8>), i32 7), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 0), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 1), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 2), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 3), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 4), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 5), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 6), i8 extractelement (<8 x i8> bitcast (i64 ptrtoint (i32 (i32)* @_Z2f2u2CMvb32_j to i64) to <8 x i8>), i32 7)>, <16 x i8>* %Funcs, align 16
114+
ret void
115+
}

0 commit comments

Comments
 (0)