summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Ziesche <florian.ziesche@gmail.com>2016-06-10 19:38:08 +0200
committerYaxun (Sam) Liu <yaxun.liu@amd.com>2016-06-10 13:38:08 -0400
commit9235f5e6fa60aaec0cd602ef7ffc5bc152ee2a53 (patch)
tree8208318bc92b5b168f4c7e3531f0d7b8501a0557
parent38e4d01b1dcc1adc4fd7d492030ee6977a954433 (diff)
extractvalue/insertvalue handling (#154)
* * fixed translation between LLVM extractvalue/insertvalue instructions and SPIR-V OpCompositeExtract/OpCompositeInsert * * added extractvalue/insertvalue test (LLVM <-> SPIR-V transcoding)
-rw-r--r--lib/SPIRV/SPIRVReader.cpp33
-rw-r--r--lib/SPIRV/SPIRVWriter.cpp14
-rw-r--r--test/transcoding/extract_insert_value.ll96
3 files changed, 132 insertions, 11 deletions
diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp
index 0908f74..f2a71c6 100644
--- a/lib/SPIRV/SPIRVReader.cpp
+++ b/lib/SPIRV/SPIRVReader.cpp
@@ -1574,13 +1574,18 @@ SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
case OpCompositeExtract: {
SPIRVCompositeExtract *CE = static_cast<SPIRVCompositeExtract *>(BV);
- assert(CE->getComposite()->getType()->isTypeVector() && "Invalid type");
- assert(CE->getIndices().size() == 1 && "Invalid index");
+ if (CE->getComposite()->getType()->isTypeVector()) {
+ assert(CE->getIndices().size() == 1 && "Invalid index");
+ return mapValue(
+ BV, ExtractElementInst::Create(
+ transValue(CE->getComposite(), F, BB),
+ ConstantInt::get(*Context, APInt(32, CE->getIndices()[0])),
+ BV->getName(), BB));
+ }
return mapValue(
- BV, ExtractElementInst::Create(
+ BV, ExtractValueInst::Create(
transValue(CE->getComposite(), F, BB),
- ConstantInt::get(*Context, APInt(32, CE->getIndices()[0])),
- BV->getName(), BB));
+ CE->getIndices(), BV->getName(), BB));
}
case OpVectorExtractDynamic: {
@@ -1589,18 +1594,24 @@ SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
BV, ExtractElementInst::Create(transValue(CE->getVector(), F, BB),
transValue(CE->getIndex(), F, BB),
BV->getName(), BB));
- }
+ }
case OpCompositeInsert: {
auto CI = static_cast<SPIRVCompositeInsert *>(BV);
- assert(CI->getComposite()->getType()->isTypeVector() && "Invalid type");
- assert(CI->getIndices().size() == 1 && "Invalid index");
+ if (CI->getComposite()->getType()->isTypeVector()) {
+ assert(CI->getIndices().size() == 1 && "Invalid index");
+ return mapValue(
+ BV, InsertElementInst::Create(
+ transValue(CI->getComposite(), F, BB),
+ transValue(CI->getObject(), F, BB),
+ ConstantInt::get(*Context, APInt(32, CI->getIndices()[0])),
+ BV->getName(), BB));
+ }
return mapValue(
- BV, InsertElementInst::Create(
+ BV, InsertValueInst::Create(
transValue(CI->getComposite(), F, BB),
transValue(CI->getObject(), F, BB),
- ConstantInt::get(*Context, APInt(32, CI->getIndices()[0])),
- BV->getName(), BB));
+ CI->getIndices(), BV->getName(), BB));
}
case OpVectorInsertDynamic: {
diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp
index d4576e4..8d2ebae 100644
--- a/lib/SPIRV/SPIRVWriter.cpp
+++ b/lib/SPIRV/SPIRVWriter.cpp
@@ -1004,6 +1004,20 @@ LLVMToSPIRV::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
BB));
}
+ if (auto Ext = dyn_cast<ExtractValueInst>(V)) {
+ return mapValue(V, BM->addCompositeExtractInst(
+ transType(Ext->getType()),
+ transValue(Ext->getAggregateOperand(), BB),
+ Ext->getIndices(), BB));
+ }
+
+ if (auto Ins = dyn_cast<InsertValueInst>(V)) {
+ return mapValue(V, BM->addCompositeInsertInst(
+ transValue(Ins->getInsertedValueOperand(), BB),
+ transValue(Ins->getAggregateOperand(), BB),
+ Ins->getIndices(), BB));
+ }
+
if (UnaryInstruction *U = dyn_cast<UnaryInstruction>(V)) {
if(isSamplerInitializer(U))
return mapValue(V, transValue(U->getOperand(0), BB));
diff --git a/test/transcoding/extract_insert_value.ll b/test/transcoding/extract_insert_value.ll
new file mode 100644
index 0000000..73bb9e2
--- /dev/null
+++ b/test/transcoding/extract_insert_value.ll
@@ -0,0 +1,96 @@
+; ModuleID = ''
+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"
+target triple = "spir-unknown-unknown"
+
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-spirv %t.bc -spirv-text -o %t.spt
+; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv %t.bc -o %t.spv
+; RUN: llvm-spirv -r %t.spv -o %t.bc
+; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM
+
+; Check 'LLVM ==> SPIR-V ==> LLVM' conversion of extractvalue/insertvalue.
+
+%struct.arr = type { [7 x float] }
+%struct.st = type { %struct.inner }
+%struct.inner = type { float }
+; CHECK-LLVM: %struct.arr = type { [7 x float] }
+; CHECK-LLVM: %struct.st = type { %struct.inner }
+; CHECK-LLVM: %struct.inner = type { float }
+
+; CHECK-LLVM: define spir_func void @array_test
+; CHECK-LLVM-LABEL: entry
+; CHECK-LLVM: %0 = getelementptr inbounds %struct.arr addrspace(1)* %object, i32 0, i32 0
+; CHECK-LLVM: %1 = load [7 x float] addrspace(1)* %0, align 4
+; CHECK-LLVM: %2 = extractvalue [7 x float] %1, 4
+; CHECK-LLVM: %3 = extractvalue [7 x float] %1, 2
+; CHECK-LLVM: %4 = fadd float %2, %3
+; CHECK-LLVM: %5 = insertvalue [7 x float] %1, float %4, 5
+; CHECK-LLVM: store [7 x float] %5, [7 x float] addrspace(1)* %0
+
+; CHECK-SPIRV-LABEL: 5 Function
+; CHECK-SPIRV-NEXT: FunctionParameter {{[0-9]+}} [[object:[0-9]+]]
+; CHECK-SPIRV: 6 InBoundsPtrAccessChain {{[0-9]+}} {{[0-9]+}} [[object]] {{[0-9]+}} {{[0-9]+}}
+; CHECK-SPIRV: 6 Load {{[0-9]+}} [[extracted_array:[0-9]+]] {{[0-9]+}} {{[0-9]+}} 4
+; CHECK-SPIRV: 5 CompositeExtract {{[0-9]+}} [[elem_4:[0-9]+]] [[extracted_array]] 4
+; CHECK-SPIRV: 5 CompositeExtract {{[0-9]+}} [[elem_2:[0-9]+]] [[extracted_array]] 2
+; CHECK-SPIRV: 5 FAdd {{[0-9]+}} [[add:[0-9]+]] [[elem_4]] [[elem_2]]
+; CHECK-SPIRV: 6 CompositeInsert {{[0-9]+}} [[inserted_array:[0-9]+]] [[add]] [[extracted_array]] 5
+; CHECK-SPIRV: 3 Store {{[0-9]+}} [[inserted_array]]
+; CHECK-SPIRV-LABEL: 1 FunctionEnd
+
+; Function Attrs: nounwind
+define spir_func void @array_test(%struct.arr addrspace(1)* %object) #0 {
+entry:
+ %0 = getelementptr inbounds %struct.arr addrspace(1)* %object, i32 0, i32 0
+ %1 = load [7 x float] addrspace(1)* %0, align 4
+ %2 = extractvalue [7 x float] %1, 4
+ %3 = extractvalue [7 x float] %1, 2
+ %4 = fadd float %2, %3
+ %5 = insertvalue [7 x float] %1, float %4, 5
+ store [7 x float] %5, [7 x float] addrspace(1)* %0
+ ret void
+}
+
+; CHECK-LLVM: define spir_func void @struct_test
+; CHECK-LLVM-LABEL: entry
+; CHECK-LLVM: %0 = getelementptr inbounds %struct.st addrspace(1)* %object, i32 0, i32 0
+; CHECK-LLVM: %1 = load %struct.inner addrspace(1)* %0, align 4
+; CHECK-LLVM: %2 = extractvalue %struct.inner %1, 0
+; CHECK-LLVM: %3 = fadd float %2, 1.000000e+00
+; CHECK-LLVM: %4 = insertvalue %struct.inner %1, float %3, 0
+; CHECK-LLVM: store %struct.inner %4, %struct.inner addrspace(1)* %0
+
+; CHECK-SPIRV-LABEL: 5 Function
+; CHECK-SPIRV-NEXT: FunctionParameter {{[0-9]+}} [[object:[0-9]+]]
+; CHECK-SPIRV: 6 InBoundsPtrAccessChain {{[0-9]+}} {{[0-9]+}} [[object]] {{[0-9]+}} {{[0-9]+}}
+; CHECK-SPIRV: 6 Load {{[0-9]+}} [[extracted_struct:[0-9]+]] {{[0-9]+}} {{[0-9]+}} 4
+; CHECK-SPIRV: 5 CompositeExtract {{[0-9]+}} [[elem:[0-9]+]] [[extracted_struct]] 0
+; CHECK-SPIRV: 5 FAdd {{[0-9]+}} [[add:[0-9]+]] [[elem]] {{[0-9]+}}
+; CHECK-SPIRV: 6 CompositeInsert {{[0-9]+}} [[inserted_struct:[0-9]+]] [[add]] [[extracted_struct]] 0
+; CHECK-SPIRV: 3 Store {{[0-9]+}} [[inserted_struct]]
+; CHECK-SPIRV-LABEL: 1 FunctionEnd
+
+; Function Attrs: nounwind
+define spir_func void @struct_test(%struct.st addrspace(1)* %object) #0 {
+entry:
+ %0 = getelementptr inbounds %struct.st addrspace(1)* %object, i32 0, i32 0
+ %1 = load %struct.inner addrspace(1)* %0, align 4
+ %2 = extractvalue %struct.inner %1, 0
+ %3 = fadd float %2, 1.000000e+00
+ %4 = insertvalue %struct.inner %1, float %3, 0
+ store %struct.inner %4, %struct.inner addrspace(1)* %0
+ ret void
+}
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!opencl.enable.FP_CONTRACT = !{}
+!opencl.spir.version = !{!0}
+!opencl.ocl.version = !{!0}
+!opencl.used.extensions = !{!1}
+!opencl.used.optional.core.features = !{!1}
+!opencl.compiler.options = !{!1}
+
+!0 = !{i32 1, i32 2}
+!1 = !{} \ No newline at end of file