Skip to content

Commit dc9bd3f

Browse files
authored
[SPIR-V] Translate complex nested vector expressions instead of lowering them (#5183)
Allow translator to go deeper into complex nested instructions. Enabled a possibility to translate expressions in `extractelement` and binary operator instructions (e.g., `fadd`, `fmul`). Also this change removes lowering for constant expression vector as the alternative approach was introduced - to translate any complicated nested instruction instead of lowering. Original commit: KhronosGroup/SPIRV-LLVM-Translator@c3c3c68b
1 parent fceb10e commit dc9bd3f

File tree

8 files changed

+277
-176
lines changed

8 files changed

+277
-176
lines changed

llvm-spirv/lib/SPIRV/SPIRVLowerConstExpr.cpp

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -167,53 +167,16 @@ void SPIRVLowerConstExprBase::visit(Module *M) {
167167
};
168168

169169
WorkList.pop_front();
170-
auto LowerConstantVec = [&II, &LowerOp, &WorkList,
171-
&M](ConstantVector *Vec,
172-
unsigned NumOfOp) -> Value * {
173-
if (std::all_of(Vec->op_begin(), Vec->op_end(), [](Value *V) {
174-
return isa<ConstantExpr>(V) || isa<Function>(V);
175-
})) {
176-
// Expand a vector of constexprs and construct it back with
177-
// series of insertelement instructions
178-
std::list<Value *> OpList;
179-
std::transform(Vec->op_begin(), Vec->op_end(),
180-
std::back_inserter(OpList),
181-
[LowerOp](Value *V) { return LowerOp(V); });
182-
Value *Repl = nullptr;
183-
unsigned Idx = 0;
184-
auto *PhiII = dyn_cast<PHINode>(II);
185-
auto *InsPoint =
186-
PhiII ? &PhiII->getIncomingBlock(NumOfOp)->back() : II;
187-
std::list<Instruction *> ReplList;
188-
for (auto V : OpList) {
189-
if (auto *Inst = dyn_cast<Instruction>(V))
190-
ReplList.push_back(Inst);
191-
Repl = InsertElementInst::Create(
192-
(Repl ? Repl : UndefValue::get(Vec->getType())), V,
193-
ConstantInt::get(Type::getInt32Ty(M->getContext()), Idx++), "",
194-
InsPoint);
195-
}
196-
WorkList.splice(WorkList.begin(), ReplList);
197-
return Repl;
198-
}
199-
return nullptr;
200-
};
201170

202171
for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) {
203172
auto *Op = II->getOperand(OI);
204-
if (auto *Vec = dyn_cast<ConstantVector>(Op)) {
205-
Value *ReplInst = LowerConstantVec(Vec, OI);
206-
if (ReplInst)
207-
II->replaceUsesOfWith(Op, ReplInst);
208-
} else if (auto CE = dyn_cast<ConstantExpr>(Op)) {
173+
if (auto *CE = dyn_cast<ConstantExpr>(Op)) {
209174
WorkList.push_front(cast<Instruction>(LowerOp(CE)));
210175
} else if (auto MDAsVal = dyn_cast<MetadataAsValue>(Op)) {
211176
Metadata *MD = MDAsVal->getMetadata();
212177
if (auto ConstMD = dyn_cast<ConstantAsMetadata>(MD)) {
213178
Constant *C = ConstMD->getValue();
214179
Value *ReplInst = nullptr;
215-
if (auto *Vec = dyn_cast<ConstantVector>(C))
216-
ReplInst = LowerConstantVec(Vec, OI);
217180
if (auto *CE = dyn_cast<ConstantExpr>(C))
218181
ReplInst = LowerOp(CE);
219182
if (ReplInst) {

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,8 @@ SPIRVValue *LLVMToSPIRVBase::transValue(Value *V, SPIRVBasicBlock *BB,
975975

976976
SPIRVDBG(dbgs() << "[transValue] " << *V << '\n');
977977
assert((!isa<Instruction>(V) || isa<GetElementPtrInst>(V) ||
978-
isa<CastInst>(V) || BB) &&
978+
isa<CastInst>(V) || isa<ExtractElementInst>(V) ||
979+
isa<BinaryOperator>(V) || BB) &&
979980
"Invalid SPIRV BB");
980981

981982
auto BV = transValueWithoutDecoration(V, BB, CreateForward, FuncTrans);
@@ -995,7 +996,9 @@ SPIRVInstruction *LLVMToSPIRVBase::transBinaryInst(BinaryOperator *B,
995996
transBoolOpCode(Op0, OpCodeMap::map(LLVMOC)), transType(B->getType()),
996997
Op0, transValue(B->getOperand(1), BB), BB);
997998

998-
if (isUnfusedMulAdd(B)) {
999+
// BinaryOperator can have no parent if it is handled as an expression inside
1000+
// another instruction.
1001+
if (B->getParent() && isUnfusedMulAdd(B)) {
9991002
Function *F = B->getFunction();
10001003
SPIRVDBG(dbgs() << "[fp-contract] disabled for " << F->getName()
10011004
<< ": possible fma candidate " << *B << '\n');

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,18 @@ SPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst) {
230230
auto OC = Inst->getOpCode();
231231
assert(isSpecConstantOpAllowedOp(OC) &&
232232
"Op code not allowed for OpSpecConstantOp");
233-
auto Ops = Inst->getIds(Inst->getOperands());
233+
std::vector<SPIRVWord> Ops;
234+
235+
// CompositeExtract/Insert operations use zero-based numbering for their
236+
// indexes (containted in instruction operands). All their operands are
237+
// Literals, so we can pass them as is for further handling.
238+
if (OC == OpCompositeExtract || OC == OpCompositeInsert) {
239+
auto *SPIRVInst = static_cast<SPIRVInstTemplateBase *>(Inst);
240+
Ops = SPIRVInst->getOpWords();
241+
} else {
242+
Ops = Inst->getIds(Inst->getOperands());
243+
}
244+
234245
Ops.insert(Ops.begin(), OC);
235246
return static_cast<SPIRVSpecConstantOp *>(SPIRVSpecConstantOp::create(
236247
OpSpecConstantOp, Inst->getType(), Inst->getId(), Ops, nullptr,

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2757,11 +2757,29 @@ _SPIRV_OP(ImageQuerySamples, true, 4)
27572757
#define _SPIRV_OP(x, ...) \
27582758
typedef SPIRVInstTemplate<SPIRVInstTemplateBase, Op##x, __VA_ARGS__> SPIRV##x;
27592759
// Other instructions
2760-
_SPIRV_OP(SpecConstantOp, true, 4, true, 0)
27612760
_SPIRV_OP(GenericPtrMemSemantics, true, 4, false)
27622761
_SPIRV_OP(GenericCastToPtrExplicit, true, 5, false, 1)
27632762
#undef _SPIRV_OP
27642763

2764+
class SPIRVSpecConstantOpBase : public SPIRVInstTemplateBase {
2765+
public:
2766+
bool isOperandLiteral(unsigned I) const override {
2767+
// If SpecConstant results from CompositeExtract/Insert operation, then all
2768+
// operands are expected to be literals.
2769+
switch (Ops[0]) { // Opcode of underlying SpecConstant operation
2770+
case OpCompositeExtract:
2771+
case OpCompositeInsert:
2772+
return true;
2773+
default:
2774+
return SPIRVInstTemplateBase::isOperandLiteral(I);
2775+
}
2776+
}
2777+
};
2778+
2779+
typedef SPIRVInstTemplate<SPIRVSpecConstantOpBase, OpSpecConstantOp, true, 4,
2780+
true, 0>
2781+
SPIRVSpecConstantOp;
2782+
27652783
class SPIRVAssumeTrueKHR : public SPIRVInstruction {
27662784
public:
27672785
static const Op OC = OpAssumeTrueKHR;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc -o %t.spv
3+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
4+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
5+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
6+
; RUN: llvm-dis %t.rev.bc
7+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
8+
9+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
10+
target triple = "spir64"
11+
12+
define linkonce_odr hidden spir_func void @foo() {
13+
entry:
14+
; CHECK-SPIRV-DAG: Constant [[#]] [[#CONSTANT1:]] 65793
15+
; CHECK-SPIRV-DAG: Constant [[#]] [[#CONSTANT2:]] 131586
16+
17+
; CHECK-SPIRV: ConstantComposite [[#]] [[#COMPOS0:]] [[#CONSTANT1]]
18+
; 124 is OpBitcast opcode
19+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#BITCAST_RES0:]] 124 [[#COMPOS0]]
20+
21+
; 81 is OpCompositeExtract opcode
22+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#EXTRACT_RES0:]] 81 [[#BITCAST_RES0]] 0
23+
; CHECK-SPIRV: ConstantComposite [[#]] [[#COMPOS1:]] [[#CONSTANT2]]
24+
25+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#BITCAST_RES1:]] 124 [[#COMPOS1]]
26+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#EXTRACT_RES1:]] 81 [[#BITCAST_RES1]] 0
27+
; 129 is OpFAdd opcode
28+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#MEMBER_1:]] 129 [[#EXTRACT_RES0:]] [[#EXTRACT_RES1]]
29+
30+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#EXTRACT_RES2:]] 81 [[#BITCAST_RES0]] 1
31+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#EXTRACT_RES3:]] 81 [[#BITCAST_RES1]] 1
32+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#MEMBER_2:]] 129 [[#EXTRACT_RES2]] [[#EXTRACT_RES3]]
33+
34+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#BITCAST_RES2:]] 81 [[#BITCAST_RES0]] 2
35+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#BITCAST_RES2:]] 81 [[#BITCAST_RES1]] 2
36+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#MEMBER_3:]] 129 [[#]] [[#BITCAST_RES2]]
37+
38+
; CHECK-SPIRV: Undef [[#]] [[#MEMBER_4:]]
39+
; CHECK-SPIRV: ConstantComposite [[#]] [[#FINAL_COMPOS:]] [[#MEMBER_1]] [[#MEMBER_2]] [[#MEMBER_3]] [[#MEMBER_4]]
40+
; CHECK-SPIRV: DebugValue [[#]] [[#FINAL_COMPOS]]
41+
42+
; CHECK-LLVM: call void @llvm.dbg.value(
43+
; CHECK-LLVM-SAME: metadata <4 x half> <
44+
; CHECK-LLVM-SAME: half fadd (
45+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 0),
46+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 0)),
47+
; CHECK-LLVM-SAME: half fadd (
48+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 1),
49+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 1)),
50+
; CHECK-LLVM-SAME: half fadd (
51+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 2),
52+
; CHECK-LLVM-SAME: half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 2)),
53+
; CHECK-LLVM-SAME: half undef>,
54+
; CHECK-LLVM-SAME: metadata ![[#]], metadata !DIExpression()), !dbg ![[#]]
55+
call void @llvm.dbg.value(
56+
metadata <4 x half> <
57+
half fadd (
58+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 0),
59+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 0)),
60+
half fadd (
61+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 1),
62+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 1)),
63+
half fadd (
64+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 65793, i32 65793> to <4 x half>), i32 2),
65+
half extractelement (<4 x half> bitcast (<2 x i32> <i32 131586, i32 131586> to <4 x half>), i32 2)),
66+
half undef>,
67+
metadata !12, metadata !DIExpression()), !dbg !7
68+
ret void
69+
}
70+
71+
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
72+
declare void @llvm.dbg.value(metadata, metadata, metadata)
73+
74+
!llvm.dbg.cu = !{!0}
75+
!llvm.module.flags = !{!3, !4}
76+
!opencl.used.extensions = !{!2}
77+
!opencl.used.optional.core.features = !{!2}
78+
!opencl.compiler.options = !{!2}
79+
!llvm.ident = !{!5}
80+
81+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/intel/llvm.git)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
82+
!1 = !DIFile(filename: "main.cpp", directory: "/export/users")
83+
!2 = !{}
84+
!3 = !{i32 2, !"Debug Info Version", i32 3}
85+
!4 = !{i32 1, !"wchar_size", i32 4}
86+
!5 = !{!"clang version 13.0.0"}
87+
!6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
88+
!7 = !DILocation(line: 1, scope: !6, inlinedAt: !11)
89+
!8 = !DISubroutineType(types: !9)
90+
!9 = !{!10}
91+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
92+
!11 = !DILocation(line: 1, column: 0, scope: !6)
93+
!12 = !DILocalVariable(name: "resVec", scope: !6, file: !1, line: 1, type: !13)
94+
!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "vec<cl::sycl::detail::half_impl::half, 3>", scope: !6, file: !1, line: 1, size: 64, flags: DIFlagTypePassByValue, elements: !2)

llvm-spirv/test/constexpr_phi.ll

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@
77
; RUN: FileCheck < %t.r.ll %s --check-prefix=CHECK-LLVM
88

99
; CHECK-SPIRV: Name [[#F:]] "_Z3runiiPi"
10+
11+
; 117 is OpConvertPtrToU opcode
12+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#SpecConst0:]] 117 [[#F1Ptr:]]
13+
; CHECK-SPIRV: SpecConstantOp [[#]] [[#SpecConst1:]] 117 [[#F2Ptr:]]
14+
; CHECK-SPIRV: ConstantComposite [[#]] [[#Compos0:]] [[#SpecConst0]] [[#SpecConst0]]
15+
; CHECK-SPIRV: ConstantComposite [[#]] [[#Compos1:]] [[#SpecConst0]] [[#SpecConst1]]
16+
1017
; CHECK-SPIRV: Function [[#]] [[#F]] [[#]] [[#]]
1118
; CHECK-SPIRV: Label [[#L1:]]
12-
; CHECK-SPIRV: CompositeInsert [[#]] [[#Ins1:]] [[#]] [[#]] 0
13-
; CHECK-SPIRV: CompositeInsert [[#]] [[#Ins2:]] [[#]] [[#Ins1]] 1
1419
; CHECK-SPIRV: BranchConditional [[#]] [[#L2:]] [[#L3:]]
1520
; CHECK-SPIRV: Label [[#L2]]
16-
; CHECK-SPIRV: CompositeInsert [[#]] [[#Ins3:]] [[#]] [[#]] 0
17-
; CHECK-SPIRV: CompositeInsert [[#]] [[#Ins4:]] [[#]] [[#Ins3]] 1
1821
; CHECK-SPIRV: Branch [[#L3]]
1922
; CHECK-SPIRV: Label [[#L3]]
2023
; CHECK-NEXT-SPIRV: Phi [[#]] [[#]]
21-
; CHECK-SAME-SPIRV: [[#Ins2]] [[#L1]]
22-
; CHECK-SAME-SPIRV: [[#Ins4]] [[#L2]]
24+
; CHECK-SAME-SPIRV: [[#Compos0]] [[#L1]]
25+
; CHECK-SAME-SPIRV: [[#Compos1]] [[#L2]]
2326

2427
; CHECK-LLVM: br label %[[#L:]]
2528
; CHECK-LLVM: [[#L]]:

0 commit comments

Comments
 (0)