@@ -120,6 +120,8 @@ void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
120
120
// Implementation
121
121
// ===----------------------------------------------------------------------===//
122
122
123
+ namespace swift {
124
+
123
125
// Define a CanonicalizeInstruction subclass for use in SILCombine.
124
126
class SILCombineCanonicalize final : CanonicalizeInstruction {
125
127
SmallSILInstructionWorklist<256 > &Worklist;
@@ -162,6 +164,8 @@ class SILCombineCanonicalize final : CanonicalizeInstruction {
162
164
}
163
165
};
164
166
167
+ } // end namespace swift
168
+
165
169
SILCombiner::SILCombiner (SILFunctionTransform *trans,
166
170
bool removeCondFails, bool enableCopyPropagation) :
167
171
parentTransform(trans),
@@ -414,99 +418,136 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) {
414
418
if (!parentTransform->continueWithNextSubpassRun (I))
415
419
return false ;
416
420
417
- // Check to see if we can DCE the instruction.
418
- if (isInstructionTriviallyDead (I)) {
419
- LLVM_DEBUG (llvm::dbgs () << " SC: DCE: " << *I << ' \n ' );
420
- eraseInstFromFunction (*I);
421
- ++NumDeadInst;
422
- MadeChange = true ;
423
- continue ;
424
- }
421
+ processInstruction (I, scCanonicalize, MadeChange);
422
+ }
423
+
424
+ Worklist.resetChecked ();
425
+ return MadeChange;
426
+ }
427
+
428
+ void SILCombiner::processInstruction (SILInstruction *I,
429
+ SILCombineCanonicalize &scCanonicalize,
430
+ bool &MadeChange) {
431
+ // Check to see if we can DCE the instruction.
432
+ if (isInstructionTriviallyDead (I)) {
433
+ LLVM_DEBUG (llvm::dbgs () << " SC: DCE: " << *I << ' \n ' );
434
+ eraseInstFromFunction (*I);
435
+ ++NumDeadInst;
436
+ MadeChange = true ;
437
+ return ;
438
+ }
425
439
#ifndef NDEBUG
426
- std::string OrigIStr;
440
+ std::string OrigIStr;
427
441
#endif
428
- LLVM_DEBUG (llvm::raw_string_ostream SS (OrigIStr); I->print (SS);
429
- OrigIStr = SS.str (););
430
- LLVM_DEBUG (llvm::dbgs () << " SC: Visiting: " << OrigIStr << ' \n ' );
442
+ LLVM_DEBUG (llvm::raw_string_ostream SS (OrigIStr); I->print (SS);
443
+ OrigIStr = SS.str (););
444
+ LLVM_DEBUG (llvm::dbgs () << " SC: Visiting: " << OrigIStr << ' \n ' );
431
445
432
- // Canonicalize the instruction.
433
- if (scCanonicalize.tryCanonicalize (I)) {
434
- MadeChange = true ;
435
- continue ;
436
- }
446
+ // Canonicalize the instruction.
447
+ if (scCanonicalize.tryCanonicalize (I)) {
448
+ MadeChange = true ;
449
+ return ;
450
+ }
437
451
438
- // If we have reached this point, all attempts to do simple simplifications
439
- // have failed. First if we have an owned forwarding value, we try to
440
- // sink. Otherwise, we perform the actual SILCombine operation.
441
- if (EnableSinkingOwnedForwardingInstToUses) {
442
- // If we have an ownership forwarding single value inst that forwards
443
- // through its first argument and it is trivially duplicatable, see if it
444
- // only has consuming uses. If so, we can duplicate the instruction into
445
- // the consuming use blocks and destroy any destroy_value uses of it that
446
- // we see. This makes it easier for SILCombine to fold instructions with
447
- // owned parameters since chains of these values will be in the same
448
- // block.
449
- if (auto *svi = dyn_cast<SingleValueInstruction>(I)) {
450
- if (auto fwdOp = ForwardingOperation (svi)) {
451
- if (fwdOp.getSingleForwardingOperand () &&
452
- SILValue (svi)->getOwnershipKind () == OwnershipKind::Owned) {
453
- // Try to sink the value. If we sank the value and deleted it,
454
- // continue. If we didn't optimize or sank but we are still able to
455
- // optimize further, we fall through to SILCombine below.
456
- if (trySinkOwnedForwardingInst (svi)) {
457
- continue ;
458
- }
452
+ // If we have reached this point, all attempts to do simple simplifications
453
+ // have failed. First if we have an owned forwarding value, we try to
454
+ // sink. Otherwise, we perform the actual SILCombine operation.
455
+ if (EnableSinkingOwnedForwardingInstToUses) {
456
+ // If we have an ownership forwarding single value inst that forwards
457
+ // through its first argument and it is trivially duplicatable, see if it
458
+ // only has consuming uses. If so, we can duplicate the instruction into
459
+ // the consuming use blocks and destroy any destroy_value uses of it that
460
+ // we see. This makes it easier for SILCombine to fold instructions with
461
+ // owned parameters since chains of these values will be in the same
462
+ // block.
463
+ if (auto *svi = dyn_cast<SingleValueInstruction>(I)) {
464
+ if (auto fwdOp = ForwardingOperation (svi)) {
465
+ if (fwdOp.getSingleForwardingOperand () &&
466
+ SILValue (svi)->getOwnershipKind () == OwnershipKind::Owned) {
467
+ // Try to sink the value. If we sank the value and deleted it,
468
+ // return. If we didn't optimize or sank but we are still able to
469
+ // optimize further, we fall through to SILCombine below.
470
+ if (trySinkOwnedForwardingInst (svi)) {
471
+ return ;
459
472
}
460
473
}
461
474
}
462
475
}
476
+ }
463
477
464
- // Then begin... SILCombine.
465
- Builder.setInsertionPoint (I);
478
+ // Then begin... SILCombine.
479
+ Builder.setInsertionPoint (I);
466
480
467
- SILInstruction *currentInst = I;
468
- if (SILInstruction *Result = visit (I)) {
469
- ++NumCombined;
470
- // Should we replace the old instruction with a new one?
471
- Worklist.replaceInstructionWithInstruction (I, Result
481
+ SILInstruction *currentInst = I;
482
+ if (SILInstruction *Result = visit (I)) {
483
+ ++NumCombined;
484
+ // Should we replace the old instruction with a new one?
485
+ Worklist.replaceInstructionWithInstruction (I, Result
472
486
#ifndef NDEBUG
473
- ,
474
- OrigIStr
487
+ ,
488
+ OrigIStr
475
489
#endif
476
- );
477
- currentInst = Result;
478
- MadeChange = true ;
479
- }
490
+ );
491
+ currentInst = Result;
492
+ MadeChange = true ;
493
+ }
480
494
481
- // Eliminate copies created that this SILCombine iteration may have
482
- // introduced during OSSA-RAUW.
483
- canonicalizeOSSALifetimes (currentInst->isDeleted () ? nullptr : currentInst);
484
-
485
- // Builder's tracking list has been accumulating instructions created by the
486
- // during this SILCombine iteration. To finish this iteration, go through
487
- // the tracking list and add its contents to the worklist and then clear
488
- // said list in preparation for the next iteration.
489
- for (SILInstruction *I : *Builder.getTrackingList ()) {
490
- if (!I->isDeleted ()) {
491
- LLVM_DEBUG (llvm::dbgs ()
492
- << " SC: add " << *I << " from tracking list to worklist\n " );
493
- Worklist.add (I);
494
- }
495
+ // Eliminate copies created that this SILCombine iteration may have
496
+ // introduced during OSSA-RAUW.
497
+ canonicalizeOSSALifetimes (currentInst->isDeleted () ? nullptr : currentInst);
498
+
499
+ // Builder's tracking list has been accumulating instructions created by the
500
+ // during this SILCombine iteration. To finish this iteration, go through
501
+ // the tracking list and add its contents to the worklist and then clear
502
+ // said list in preparation for the next iteration.
503
+ for (SILInstruction *I : *Builder.getTrackingList ()) {
504
+ if (!I->isDeleted ()) {
505
+ LLVM_DEBUG (llvm::dbgs ()
506
+ << " SC: add " << *I << " from tracking list to worklist\n " );
507
+ Worklist.add (I);
495
508
}
496
- Builder.getTrackingList ()->clear ();
497
509
}
498
-
499
- Worklist.resetChecked ();
500
- return MadeChange;
510
+ Builder.getTrackingList ()->clear ();
501
511
}
502
512
513
+ namespace swift ::test {
514
+ struct SILCombinerProcessInstruction {
515
+ void operator ()(SILCombiner &combiner, SILInstruction *inst,
516
+ SILCombineCanonicalize &canonicalizer, bool &madeChange) {
517
+ combiner.processInstruction (inst, canonicalizer, madeChange);
518
+ }
519
+ };
520
+ // Arguments:
521
+ // - instruction: the instruction to be processed
522
+ // - bool: remove cond_fails
523
+ // - bool: enable lifetime canonicalization
524
+ // Dumps:
525
+ // - the function after the processing is attempted
526
+ static FunctionTest SILCombineProcessInstruction (
527
+ " sil_combine_process_instruction" ,
528
+ [](auto &function, auto &arguments, auto &test) {
529
+ auto inst = arguments.takeInstruction ();
530
+ auto removeCondFails = arguments.takeBool ();
531
+ auto enableCopyPropagation = arguments.takeBool ();
532
+ SILCombiner combiner (test.getPass (), removeCondFails,
533
+ enableCopyPropagation);
534
+ SILCombineCanonicalize canonicalizer (combiner.Worklist ,
535
+ *test.getDeadEndBlocks ());
536
+ bool madeChange = false ;
537
+ SILCombinerProcessInstruction ()(combiner, inst, canonicalizer,
538
+ madeChange);
539
+ function.dump ();
540
+ });
541
+ } // end namespace swift::test
542
+
503
543
namespace swift ::test {
504
544
// Arguments:
505
- // - instruction: the instruction to be canonicalized
545
+ // - instruction: the instruction to be visited
506
546
// Dumps:
507
- // - the function after the canonicalization is attempted
508
- static FunctionTest SILCombineCanonicalizeInstruction (
509
- " sil_combine_instruction" , [](auto &function, auto &arguments, auto &test) {
547
+ // - the function after the visitation is attempted
548
+ static FunctionTest SILCombineVisitInstruction (
549
+ " sil_combine_visit_instruction" ,
550
+ [](auto &function, auto &arguments, auto &test) {
510
551
SILCombiner combiner (test.getPass (), false , false );
511
552
auto inst = arguments.takeInstruction ();
512
553
combiner.Builder .setInsertionPoint (inst);
0 commit comments