Skip to content

Commit c5d3547

Browse files
delecuijsji
authored andcommitted
Refactor switch function creation to generate single return point (#2714)
The refactoring is to simplify the vectorization of generated functions. Signed-off-by: Cui, Dele <dele.cui@intel.com> Original commit: KhronosGroup/SPIRV-LLVM-Translator@a5952614c12594c
1 parent bbe9438 commit c5d3547

File tree

6 files changed

+144
-55
lines changed

6 files changed

+144
-55
lines changed

llvm-spirv/lib/SPIRV/OCLUtil.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -535,17 +535,18 @@ getOrCreateSwitchFunc(StringRef MapName, Value *V,
535535
F->setLinkage(GlobalValue::PrivateLinkage);
536536

537537
LLVMContext &Ctx = M->getContext();
538-
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
539-
IRBuilder<> IRB(BB);
538+
BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", F);
539+
IRBuilder<> EntryIRB(EntryBB);
540+
AllocaInst *Result = EntryIRB.CreateAlloca(Ty, nullptr, "result");
540541
SwitchInst *SI;
541542
F->arg_begin()->setName("key");
542543
if (KeyMask) {
543544
Value *MaskV = ConstantInt::get(Type::getInt32Ty(Ctx), KeyMask);
544-
Value *NewKey = IRB.CreateAnd(MaskV, F->arg_begin());
545+
Value *NewKey = EntryIRB.CreateAnd(MaskV, F->arg_begin());
545546
NewKey->setName("key.masked");
546-
SI = IRB.CreateSwitch(NewKey, BB);
547+
SI = EntryIRB.CreateSwitch(NewKey, EntryBB);
547548
} else {
548-
SI = IRB.CreateSwitch(F->arg_begin(), BB);
549+
SI = EntryIRB.CreateSwitch(F->arg_begin(), EntryBB);
549550
}
550551

551552
if (!DefaultCase) {
@@ -555,17 +556,27 @@ getOrCreateSwitchFunc(StringRef MapName, Value *V,
555556
SI->setDefaultDest(DefaultBB);
556557
}
557558

559+
BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
560+
BasicBlock *CaseBB = nullptr;
558561
Map.foreach ([&](int Key, int Val) {
559562
if (IsReverse)
560563
std::swap(Key, Val);
561-
BasicBlock *CaseBB = BasicBlock::Create(Ctx, "case." + Twine(Key), F);
564+
CaseBB = BasicBlock::Create(Ctx, "case." + Twine(Key), F);
562565
IRBuilder<> CaseIRB(CaseBB);
563-
CaseIRB.CreateRet(CaseIRB.getInt32(Val));
564-
SI->addCase(IRB.getInt32(Key), CaseBB);
566+
CaseIRB.CreateStore(CaseIRB.getInt32(Val), Result);
567+
CaseIRB.CreateBr(ExitBB);
568+
SI->addCase(EntryIRB.getInt32(Key), CaseBB);
565569
if (Key == DefaultCase)
566570
SI->setDefaultDest(CaseBB);
567571
});
568-
assert(SI->getDefaultDest() != BB && "Invalid default destination in switch");
572+
573+
ExitBB->moveAfter(CaseBB);
574+
IRBuilder<> ExitIRB(ExitBB);
575+
LoadInst *RetVal = ExitIRB.CreateLoad(Ty, Result, "retVal");
576+
ExitIRB.CreateRet(RetVal);
577+
578+
assert(SI->getDefaultDest() != EntryBB &&
579+
"Invalid default destination in switch");
569580
return addCallInst(M, MapName, Ty, V, nullptr, InsertPoint);
570581
}
571582

llvm-spirv/test/atomic_explicit_arguments.spt

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
; CHECK: define private spir_func i32 @__translate_spirv_memory_scope(i32 %key) {
4646
; CHECK: entry:
47+
; CHECK: %result = alloca i32, align 4
4748
; CHECK: switch i32 %key, label %default [
4849
; CHECK: i32 4, label %case.4
4950
; CHECK: i32 2, label %case.2
@@ -54,19 +55,28 @@
5455
; CHECK: default:
5556
; CHECK: unreachable
5657
; CHECK: case.4:
57-
; CHECK: ret i32 0
58+
; CHECK: store i32 0, ptr %result, align 4
59+
; CHECK: br label %exit
5860
; CHECK: case.2:
59-
; CHECK: ret i32 1
61+
; CHECK: store i32 1, ptr %result, align 4
62+
; CHECK: br label %exit
6063
; CHECK: case.1:
61-
; CHECK: ret i32 2
64+
; CHECK: store i32 2, ptr %result, align 4
65+
; CHECK: br label %exit
6266
; CHECK: case.0:
63-
; CHECK: ret i32 3
67+
; CHECK: store i32 3, ptr %result, align 4
68+
; CHECK: br label %exit
6469
; CHECK: case.3:
65-
; CHECK: ret i32 4
70+
; CHECK: store i32 4, ptr %result, align 4
71+
; CHECK: br label %exit
72+
; CHECK: exit:
73+
; CHECK: %retVal = load i32, ptr %result, align 4
74+
; CHECK: ret i32 %retVal
6675
; CHECK: }
6776

6877
; CHECK: define private spir_func i32 @__translate_spirv_memory_order(i32 %key) {
6978
; CHECK: entry:
79+
; CHECK: %result = alloca i32, align 4
7080
; CHECK: %key.masked = and i32 30, %key
7181
; CHECK: switch i32 %key.masked, label %default [
7282
; CHECK: i32 0, label %case.0
@@ -78,13 +88,21 @@
7888
; CHECK: default:
7989
; CHECK: unreachable
8090
; CHECK: case.0:
81-
; CHECK: ret i32 0
91+
; CHECK: store i32 0, ptr %result, align 4
92+
; CHECK: br label %exit
8293
; CHECK: case.2:
83-
; CHECK: ret i32 2
94+
; CHECK: store i32 2, ptr %result, align 4
95+
; CHECK: br label %exit
8496
; CHECK: case.4:
85-
; CHECK: ret i32 3
97+
; CHECK: store i32 3, ptr %result, align 4
98+
; CHECK: br label %exit
8699
; CHECK: case.8:
87-
; CHECK: ret i32 4
100+
; CHECK: store i32 4, ptr %result, align 4
101+
; CHECK: br label %exit
88102
; CHECK: case.16:
89-
; CHECK: ret i32 5
103+
; CHECK: store i32 5, ptr %result, align 4
104+
; CHECK: br label %exit
105+
; CHECK: exit:
106+
; CHECK: %retVal = load i32, ptr %result, align 4
107+
; CHECK: ret i32 %retVal
90108
; CHECK: }

llvm-spirv/test/barrier_explicit_arguments.spt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@
3939
; CHECK-12: call spir_func void @_Z7barrierj(i32 %call1)
4040
; CHECK-20: call spir_func void @_Z18work_group_barrierj12memory_scope(i32 %call
4141
; CHECK-20: call spir_func void @_Z17sub_group_barrierj12memory_scope(i32 %call
42-
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key)
42+
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key) {
4343
; CHECK: entry:
44+
; CHECK: %result = alloca i32, align 4
4445
; CHECK: %key.masked = and i32 2816, %key
4546
; CHECK: switch i32 %key.masked, label %default [
4647
; CHECK: i32 256, label %case.256
@@ -54,17 +55,27 @@
5455
; CHECK: default:
5556
; CHECK: unreachable
5657
; CHECK: case.256:
57-
; CHECK: ret i32 1
58+
; CHECK: store i32 1, ptr %result, align 4
59+
; CHECK: br label %exit
5860
; CHECK: case.512:
59-
; CHECK: ret i32 2
61+
; CHECK: store i32 2, ptr %result, align 4
62+
; CHECK: br label %exit
6063
; CHECK: case.768:
61-
; CHECK: ret i32 3
64+
; CHECK: store i32 3, ptr %result, align 4
65+
; CHECK: br label %exit
6266
; CHECK: case.2048:
63-
; CHECK: ret i32 4
67+
; CHECK: store i32 4, ptr %result, align 4
68+
; CHECK: br label %exit
6469
; CHECK: case.2304:
65-
; CHECK: ret i32 5
70+
; CHECK: store i32 5, ptr %result, align 4
71+
; CHECK: br label %exit
6672
; CHECK: case.2560:
67-
; CHECK: ret i32 6
73+
; CHECK: store i32 6, ptr %result, align 4
74+
; CHECK: br label %exit
6875
; CHECK: case.2816:
69-
; CHECK: ret i32 7
76+
; CHECK: store i32 7, ptr %result, align 4
77+
; CHECK: br label %exit
78+
; CHECK: exit:
79+
; CHECK: %retVal = load i32, ptr %result, align 4
80+
; CHECK: ret i32 %retVal
7081
; CHECK: }

llvm-spirv/test/mem_fence_explicit_arguments.spt

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@
4444
; CHECK-20: %call3 = call spir_func i32 @__translate_spirv_memory_fence(i32 %[[VAL1]])
4545
; CHECK-20: %call4 = call spir_func i32 @__translate_spirv_memory_order(i32 %[[VAL1]])
4646
; CHECK-20: call spir_func void @_Z22atomic_work_item_fencej12memory_order12memory_scope(i32 %call3, i32 %call4, i32 %call2)
47-
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key)
47+
; CHECK: define private spir_func i32 @__translate_spirv_memory_fence(i32 %key) {
4848
; CHECK: entry:
49+
; CHECK: %result = alloca i32, align 4
4950
; CHECK: %key.masked = and i32 2816, %key
5051
; CHECK: switch i32 %key.masked, label %default [
5152
; CHECK: i32 256, label %case.256
@@ -59,22 +60,33 @@
5960
; CHECK: default:
6061
; CHECK: unreachable
6162
; CHECK: case.256:
62-
; CHECK: ret i32 1
63+
; CHECK: store i32 1, ptr %result, align 4
64+
; CHECK: br label %exit
6365
; CHECK: case.512:
64-
; CHECK: ret i32 2
66+
; CHECK: store i32 2, ptr %result, align 4
67+
; CHECK: br label %exit
6568
; CHECK: case.768:
66-
; CHECK: ret i32 3
69+
; CHECK: store i32 3, ptr %result, align 4
70+
; CHECK: br label %exit
6771
; CHECK: case.2048:
68-
; CHECK: ret i32 4
72+
; CHECK: store i32 4, ptr %result, align 4
73+
; CHECK: br label %exit
6974
; CHECK: case.2304:
70-
; CHECK: ret i32 5
75+
; CHECK: store i32 5, ptr %result, align 4
76+
; CHECK: br label %exit
7177
; CHECK: case.2560:
72-
; CHECK: ret i32 6
78+
; CHECK: store i32 6, ptr %result, align 4
79+
; CHECK: br label %exit
7380
; CHECK: case.2816:
74-
; CHECK: ret i32 7
81+
; CHECK: store i32 7, ptr %result, align 4
82+
; CHECK: br label %exit
83+
; CHECK: exit:
84+
; CHECK: %retVal = load i32, ptr %result, align 4
85+
; CHECK: ret i32 %retVal
7586
; CHECK: }
7687
; CHECK-20: define private spir_func i32 @__translate_spirv_memory_order(i32 %key) {
7788
; CHECK-20: entry:
89+
; CHECK-20: %result = alloca i32, align 4
7890
; CHECK-20: %key.masked = and i32 30, %key
7991
; CHECK-20: switch i32 %key.masked, label %default [
8092
; CHECK-20: i32 0, label %case.0
@@ -86,13 +98,21 @@
8698
; CHECK-20: default:
8799
; CHECK-20: unreachable
88100
; CHECK-20: case.0:
89-
; CHECK-20: ret i32 0
101+
; CHECK-20: store i32 0, ptr %result, align 4
102+
; CHECK-20: br label %exit
90103
; CHECK-20: case.2:
91-
; CHECK-20: ret i32 2
104+
; CHECK-20: store i32 2, ptr %result, align 4
105+
; CHECK-20: br label %exit
92106
; CHECK-20: case.4:
93-
; CHECK-20: ret i32 3
107+
; CHECK-20: store i32 3, ptr %result, align 4
108+
; CHECK-20: br label %exit
94109
; CHECK-20: case.8:
95-
; CHECK-20: ret i32 4
110+
; CHECK-20: store i32 4, ptr %result, align 4
111+
; CHECK-20: br label %exit
96112
; CHECK-20: case.16:
97-
; CHECK-20: ret i32 5
113+
; CHECK-20: store i32 5, ptr %result, align 4
114+
; CHECK-20: br label %exit
115+
; CHECK-20: exit:
116+
; CHECK-20: %retVal = load i32, ptr %result, align 4
117+
; CHECK-20: ret i32 %retVal
98118
; CHECK-20: }

llvm-spirv/test/transcoding/atomic_explicit_arguments.cl

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// clang-format off
2+
13
// RUN: %clang_cc1 -triple spir -cl-std=cl2.0 %s -fdeclare-opencl-builtins -finclude-default-header -emit-llvm-bc -o %t.bc
24
// RUN: llvm-spirv %t.bc -o %t.spv
35
// RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
@@ -31,32 +33,50 @@ int load (volatile atomic_int* obj, memory_order order, memory_scope scope) {
3133

3234
// CHECK-SPIRV: Function [[int]] [[TRANS_MEM_SCOPE]]
3335
// CHECK-SPIRV: FunctionParameter [[int]] [[KEY:[0-9]+]]
36+
// CHECK-SPIRV: Variable {{[0-9]+}} [[RES:[0-9]+]]
3437
// CHECK-SPIRV: Switch [[KEY]] [[CASE_2:[0-9]+]] 0 [[CASE_0:[0-9]+]] 1 [[CASE_1:[0-9]+]] 2 [[CASE_2]] 3 [[CASE_3:[0-9]+]] 4 [[CASE_4:[0-9]+]]
3538
// CHECK-SPIRV: Label [[CASE_0]]
36-
// CHECK-SPIRV: ReturnValue [[FOUR]]
39+
// CHECK-SPIRV: Store [[RES]] [[FOUR]]
40+
// CHECK-SPIRV: Branch [[EXIT:[0-9]+]]
3741
// CHECK-SPIRV: Label [[CASE_1]]
38-
// CHECK-SPIRV: ReturnValue [[TWO]]
42+
// CHECK-SPIRV: Store [[RES]] [[TWO]]
43+
// CHECK-SPIRV: Branch [[EXIT]]
3944
// CHECK-SPIRV: Label [[CASE_2]]
40-
// CHECK-SPIRV: ReturnValue [[ONE]]
45+
// CHECK-SPIRV: Store [[RES]] [[ONE]]
46+
// CHECK-SPIRV: Branch [[EXIT]]
4147
// CHECK-SPIRV: Label [[CASE_3]]
42-
// CHECK-SPIRV: ReturnValue [[ZERO]]
48+
// CHECK-SPIRV: Store [[RES]] [[ZERO]]
49+
// CHECK-SPIRV: Branch [[EXIT]]
4350
// CHECK-SPIRV: Label [[CASE_4]]
44-
// CHECK-SPIRV: ReturnValue [[THREE]]
51+
// CHECK-SPIRV: Store [[RES]] [[THREE]]
52+
// CHECK-SPIRV: Branch [[EXIT]]
53+
// CHECK-SPIRV: Label [[EXIT]]
54+
// CHECK-SPIRV: Load [[int]] [[RET_VAR:[0-9]+]] [[RES]]
55+
// CHECK-SPIRV: ReturnValue [[RET_VAR]]
4556
// CHECK-SPIRV: FunctionEnd
4657

4758
// CHECK-SPIRV: Function [[int]] [[TRANS_MEM_ORDER]]
4859
// CHECK-SPIRV: FunctionParameter [[int]] [[KEY:[0-9]+]]
60+
// CHECK-SPIRV: Variable {{[0-9]+}} [[RES:[0-9]+]]
4961
// CHECK-SPIRV: Switch [[KEY]] [[CASE_5:[0-9]+]] 0 [[CASE_0:[0-9]+]] 2 [[CASE_2:[0-9]+]] 3 [[CASE_3:[0-9]+]] 4 [[CASE_4:[0-9]+]] 5 [[CASE_5]]
5062
// CHECK-SPIRV: Label [[CASE_0]]
51-
// CHECK-SPIRV: ReturnValue [[ZERO]]
63+
// CHECK-SPIRV: Store [[RES]] [[ZERO]]
64+
// CHECK-SPIRV: Branch [[EXIT:[0-9]+]]
5265
// CHECK-SPIRV: Label [[CASE_2]]
53-
// CHECK-SPIRV: ReturnValue [[TWO]]
66+
// CHECK-SPIRV: Store [[RES]] [[TWO]]
67+
// CHECK-SPIRV: Branch [[EXIT]]
5468
// CHECK-SPIRV: Label [[CASE_3]]
55-
// CHECK-SPIRV: ReturnValue [[FOUR]]
69+
// CHECK-SPIRV: Store [[RES]] [[FOUR]]
70+
// CHECK-SPIRV: Branch [[EXIT]]
5671
// CHECK-SPIRV: Label [[CASE_4]]
57-
// CHECK-SPIRV: ReturnValue [[EIGHT]]
72+
// CHECK-SPIRV: Store [[RES]] [[EIGHT]]
73+
// CHECK-SPIRV: Branch [[EXIT]]
5874
// CHECK-SPIRV: Label [[CASE_5]]
59-
// CHECK-SPIRV: ReturnValue [[SIXTEEN]]
75+
// CHECK-SPIRV: Store [[RES]] [[SIXTEEN]]
76+
// CHECK-SPIRV: Branch [[EXIT]]
77+
// CHECK-SPIRV: Label [[EXIT]]
78+
// CHECK-SPIRV: Load [[int]] [[RET_VAR:[0-9]+]] [[RES]]
79+
// CHECK-SPIRV: ReturnValue [[RET_VAR]]
6080
// CHECK-SPIRV: FunctionEnd
6181

6282

llvm-spirv/test/transcoding/barrier-runtime-scope.ll

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
; CHECK-LLVM: define private spir_func i32 @__translate_spirv_memory_scope(i32 %key) {
2525
; CHECK-LLVM: entry:
26+
; CHECK-LLVM: %result = alloca i32, align 4
2627
; CHECK-LLVM: switch i32 %key, label %default [
2728
; CHECK-LLVM: i32 4, label %case.4
2829
; CHECK-LLVM: i32 2, label %case.2
@@ -33,15 +34,23 @@
3334
; CHECK-LLVM: default: ; preds = %entry
3435
; CHECK-LLVM: unreachable
3536
; CHECK-LLVM: case.4: ; preds = %entry
36-
; CHECK-LLVM: ret i32 0
37+
; CHECK-LLVM: store i32 0, ptr %result, align 4
38+
; CHECK-LLVM: br label %exit
3739
; CHECK-LLVM: case.2: ; preds = %entry
38-
; CHECK-LLVM: ret i32 1
40+
; CHECK-LLVM: store i32 1, ptr %result, align 4
41+
; CHECK-LLVM: br label %exit
3942
; CHECK-LLVM: case.1: ; preds = %entry
40-
; CHECK-LLVM: ret i32 2
43+
; CHECK-LLVM: store i32 2, ptr %result, align 4
44+
; CHECK-LLVM: br label %exit
4145
; CHECK-LLVM: case.0: ; preds = %entry
42-
; CHECK-LLVM: ret i32 3
46+
; CHECK-LLVM: store i32 3, ptr %result, align 4
47+
; CHECK-LLVM: br label %exit
4348
; CHECK-LLVM: case.3: ; preds = %entry
44-
; CHECK-LLVM: ret i32 4
49+
; CHECK-LLVM: store i32 4, ptr %result, align 4
50+
; CHECK-LLVM: br label %exit
51+
; CHECK-LLVM: exit: ; preds = %case.3, %case.0, %case.1, %case.2, %case.4
52+
; CHECK-LLVM: %retVal = load i32, ptr %result, align 4
53+
; CHECK-LLVM: ret i32 %retVal
4554
; CHECK-LLVM: }
4655

4756
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"

0 commit comments

Comments
 (0)