@@ -1142,6 +1142,42 @@ class SPIRVStructurizer : public FunctionPass {
1142
1142
return Modified;
1143
1143
}
1144
1144
1145
+ // Makes sure every case target in |F| is unique. If 2 cases branch to the
1146
+ // same basic block, one of the targets is updated so it jumps to a new basic
1147
+ // block ending with a single unconditional branch to the original target.
1148
+ bool splitSwitchCases (Function &F) {
1149
+ bool Modified = false ;
1150
+
1151
+ for (BasicBlock &BB : F) {
1152
+ SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator ());
1153
+ if (!SI)
1154
+ continue ;
1155
+
1156
+ BlockSet Seen;
1157
+ Seen.insert (SI->getDefaultDest ());
1158
+
1159
+ auto It = SI->case_begin ();
1160
+ while (It != SI->case_end ()) {
1161
+ BasicBlock *Target = It->getCaseSuccessor ();
1162
+ if (Seen.count (Target) == 0 ) {
1163
+ Seen.insert (Target);
1164
+ ++It;
1165
+ continue ;
1166
+ }
1167
+
1168
+ Modified = true ;
1169
+ BasicBlock *NewTarget =
1170
+ BasicBlock::Create (F.getContext (), " new.sw.case" , &F);
1171
+ IRBuilder<> Builder (NewTarget);
1172
+ Builder.CreateBr (Target);
1173
+ SI->addCase (It->getCaseValue (), NewTarget);
1174
+ It = SI->removeCase (It);
1175
+ }
1176
+ }
1177
+
1178
+ return Modified;
1179
+ }
1180
+
1145
1181
bool IsRequiredForPhiNode (BasicBlock *BB) {
1146
1182
for (BasicBlock *Successor : successors (BB)) {
1147
1183
for (PHINode &Phi : Successor->phis ()) {
@@ -1269,6 +1305,11 @@ class SPIRVStructurizer : public FunctionPass {
1269
1305
virtual bool runOnFunction (Function &F) override {
1270
1306
bool Modified = false ;
1271
1307
1308
+ // In LLVM, Switches are allowed to have several cases branching to the same
1309
+ // basic block. This is allowed in SPIR-V, but can make structurizing SPIR-V
1310
+ // harder, so first remove edge cases.
1311
+ Modified |= splitSwitchCases (F);
1312
+
1272
1313
// LLVM allows conditional branches to have both side jumping to the same
1273
1314
// block. It also allows switched to have a single default, or just one
1274
1315
// case. Cleaning this up now.
0 commit comments