11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#define DEBUG_TYPE " condbranch-forwarding"
14
- #include " swift/SILOptimizer/PassManager/Passes.h"
15
- #include " swift/SILOptimizer/PassManager/Transforms.h"
16
- #include " swift/SIL/SILInstruction.h"
17
- #include " swift/SIL/SILArgument.h"
14
+ #include " swift/SIL/BasicBlockBits.h"
18
15
#include " swift/SIL/DebugUtils.h"
16
+ #include " swift/SIL/OwnershipUtils.h"
17
+ #include " swift/SIL/SILArgument.h"
19
18
#include " swift/SIL/SILBuilder.h"
19
+ #include " swift/SIL/SILInstruction.h"
20
20
#include " swift/SIL/SILUndef.h"
21
- #include " swift/SIL/BasicBlockBits.h"
21
+ #include " swift/SILOptimizer/PassManager/Passes.h"
22
+ #include " swift/SILOptimizer/PassManager/Transforms.h"
22
23
23
24
using namespace swift ;
24
25
@@ -101,15 +102,12 @@ class ConditionForwarding : public SILFunctionTransform {
101
102
102
103
// / The entry point to the transformation.
103
104
void run () override {
104
- LLVM_DEBUG (llvm::dbgs () << " ** StackPromotion **\n " );
105
-
106
105
bool Changed = false ;
107
106
108
107
SILFunction *F = getFunction ();
109
108
110
- // FIXME: Add ownership support.
111
- if (F->hasOwnership ())
112
- return ;
109
+ LLVM_DEBUG (llvm::dbgs ()
110
+ << " ** ConditionForwarding on " << F->getName () << " **\n " );
113
111
114
112
for (SILBasicBlock &BB : *F) {
115
113
if (auto *SEI = dyn_cast<SwitchEnumInst>(BB.getTerminator ())) {
@@ -143,6 +141,11 @@ static bool hasNoRelevantSideEffects(SILBasicBlock *BB) {
143
141
return false ;
144
142
continue ;
145
143
}
144
+ if (isa<BeginBorrowInst>(&I) || isa<EndBorrowInst>(&I)) {
145
+ continue ;
146
+ }
147
+ LLVM_DEBUG (llvm::dbgs () << " Bailing out, found inst with side-effects " );
148
+ LLVM_DEBUG (I.dump ());
146
149
return false ;
147
150
}
148
151
return true ;
@@ -226,6 +229,15 @@ bool ConditionForwarding::tryOptimize(SwitchEnumInst *SEI) {
226
229
if (CommonBranchBlock->getSuccessors ().size () != PredBlocks.size ())
227
230
return false ;
228
231
232
+ if (getFunction ()->hasOwnership ()) {
233
+ // TODO: Currently disabled because this case may need lifetime extension
234
+ // Disabling this conservatively for now.
235
+ assert (Condition->getNumOperands () == 1 );
236
+ BorrowedValue conditionOp (Condition->getOperand (0 ));
237
+ if (conditionOp && conditionOp.isLocalScope ()) {
238
+ return false ;
239
+ }
240
+ }
229
241
// Now do the transformation!
230
242
// First thing to do is to replace all uses of the Enum (= the merging block
231
243
// argument), as this argument gets deleted.
@@ -247,8 +259,8 @@ bool ConditionForwarding::tryOptimize(SwitchEnumInst *SEI) {
247
259
SILArgument *NewArg = nullptr ;
248
260
if (NeedEnumArg.insert (UseBlock)) {
249
261
// The first Enum use in this UseBlock.
250
- NewArg =
251
- UseBlock-> createPhiArgument ( Arg->getType (), OwnershipKind::Owned );
262
+ NewArg = UseBlock-> createPhiArgument (Arg-> getType (),
263
+ Arg->getOwnershipKind () );
252
264
} else {
253
265
// We already inserted the Enum argument for this UseBlock.
254
266
assert (UseBlock->getNumArguments () >= 1 );
@@ -281,10 +293,30 @@ bool ConditionForwarding::tryOptimize(SwitchEnumInst *SEI) {
281
293
if (HasEnumArg) {
282
294
// The successor block has a new argument (which we created above) where
283
295
// we have to pass the Enum.
296
+ assert (!getFunction ()->hasOwnership () ||
297
+ EI->getType ().isTrivial (*getFunction ()));
284
298
BranchArgs.push_back (EI);
285
299
}
286
300
B.createBranch (BI->getLoc (), SEDest, BranchArgs);
287
301
BI->eraseFromParent ();
302
+ if (EI->use_empty ()) {
303
+ assert (!HasEnumArg);
304
+ EI->eraseFromParent ();
305
+ } else {
306
+ // If an @owned EI has uses remaining, ownership fixup is needed.
307
+ // 1. Create a copy_value of EI's operand and
308
+ // use it in the branch to avoid a double-consume.
309
+ // 2. Create a destroy_value of EI, to avoid a leak.
310
+ if (getFunction ()->hasOwnership () && EI->hasOperand () &&
311
+ EI->getOwnershipKind () == OwnershipKind::Owned) {
312
+ auto *term = EI->getParent ()->getTerminator ();
313
+ assert (!HasEnumArg);
314
+ auto *copy = SILBuilderWithScope (EI).createCopyValue (EI->getLoc (),
315
+ EI->getOperand ());
316
+ term->getOperandRef (0 ).set (copy);
317
+ SILBuilderWithScope (term).createDestroyValue (EI->getLoc (), EI);
318
+ }
319
+ }
288
320
}
289
321
290
322
// Final step: replace the switch_enum by the condition.
0 commit comments