@@ -120,6 +120,8 @@ void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
120120// Implementation
121121// ===----------------------------------------------------------------------===//
122122
123+ namespace swift {
124+
123125// Define a CanonicalizeInstruction subclass for use in SILCombine.
124126class SILCombineCanonicalize final : CanonicalizeInstruction {
125127 SmallSILInstructionWorklist<256 > &Worklist;
@@ -162,6 +164,8 @@ class SILCombineCanonicalize final : CanonicalizeInstruction {
162164 }
163165};
164166
167+ } // end namespace swift
168+
165169SILCombiner::SILCombiner (SILFunctionTransform *trans,
166170 bool removeCondFails, bool enableCopyPropagation) :
167171 parentTransform(trans),
@@ -414,99 +418,136 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) {
414418 if (!parentTransform->continueWithNextSubpassRun (I))
415419 return false ;
416420
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+ }
425439#ifndef NDEBUG
426- std::string OrigIStr;
440+ std::string OrigIStr;
427441#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 ' );
431445
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+ }
437451
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 ;
459472 }
460473 }
461474 }
462475 }
476+ }
463477
464- // Then begin... SILCombine.
465- Builder.setInsertionPoint (I);
478+ // Then begin... SILCombine.
479+ Builder.setInsertionPoint (I);
466480
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
472486#ifndef NDEBUG
473- ,
474- OrigIStr
487+ ,
488+ OrigIStr
475489#endif
476- );
477- currentInst = Result;
478- MadeChange = true ;
479- }
490+ );
491+ currentInst = Result;
492+ MadeChange = true ;
493+ }
480494
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);
495508 }
496- Builder.getTrackingList ()->clear ();
497509 }
498-
499- Worklist.resetChecked ();
500- return MadeChange;
510+ Builder.getTrackingList ()->clear ();
501511}
502512
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+
503543namespace swift ::test {
504544// Arguments:
505- // - instruction: the instruction to be canonicalized
545+ // - instruction: the instruction to be visited
506546// 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) {
510551 SILCombiner combiner (test.getPass (), false , false );
511552 auto inst = arguments.takeInstruction ();
512553 combiner.Builder .setInsertionPoint (inst);
0 commit comments