@@ -829,7 +829,7 @@ getEnumCaseRecursive(SILValue Val, SILBasicBlock *UsedInBB, int RecursionDepth,
829
829
Pred = UsedInBB->getSinglePredecessorBlock ();
830
830
}
831
831
832
- // In case of a block argument , recursively check the enum cases of all
832
+ // In case of a phi , recursively check the enum cases of all
833
833
// incoming predecessors.
834
834
if (auto *Arg = dyn_cast<SILArgument>(Val)) {
835
835
HandledArgs.insert (Arg);
@@ -2697,8 +2697,6 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
2697
2697
bool SimplifyCFG::simplifyTermWithIdenticalDestBlocks (SILBasicBlock *BB) {
2698
2698
TrampolineDest commonDest;
2699
2699
for (auto *SuccBlock : BB->getSuccessorBlocks ()) {
2700
- if (SuccBlock->getNumArguments () != 0 )
2701
- return false ;
2702
2700
auto trampolineDest = TrampolineDest (BB, SuccBlock);
2703
2701
if (!trampolineDest) {
2704
2702
return false ;
@@ -2911,11 +2909,7 @@ bool SimplifyCFG::simplifyBlocks() {
2911
2909
// / Canonicalize all switch_enum and switch_enum_addr instructions.
2912
2910
// / If possible, replace the default with the corresponding unique case.
2913
2911
bool SimplifyCFG::canonicalizeSwitchEnums () {
2914
- if (!EnableOSSARewriteTerminator && Fn.hasOwnership ()) {
2915
- // TODO: OSSA. In OSSA, the default switch_enum case passes the
2916
- // original enum as a block argument. This needs to check that the block
2917
- // argument is dead, then replace it with the a new argument for the default
2918
- // payload.
2912
+ if (!EnableOSSASimplifyCFG && Fn.hasOwnership ()) {
2919
2913
return false ;
2920
2914
}
2921
2915
bool Changed = false ;
@@ -2933,6 +2927,15 @@ bool SimplifyCFG::canonicalizeSwitchEnums() {
2933
2927
if (!elementDecl)
2934
2928
continue ;
2935
2929
2930
+ if (!EnableOSSARewriteTerminator && Fn.hasOwnership ()) {
2931
+ if (!SWI.getOperand ()->getType ().isTrivial (Fn)) {
2932
+ // TODO: OSSA. In OSSA, the default switch_enum case passes the original
2933
+ // enum as a block argument. This needs to check that the block argument
2934
+ // is dead, then replace it with the a new argument for the default
2935
+ // payload.
2936
+ continue ;
2937
+ }
2938
+ }
2936
2939
LLVM_DEBUG (llvm::dbgs () << " simplify canonical switch_enum\n " );
2937
2940
2938
2941
// Construct a new instruction by copying all the case entries.
@@ -2941,9 +2944,25 @@ bool SimplifyCFG::canonicalizeSwitchEnums() {
2941
2944
CaseBBs.push_back (SWI.getCase (idx));
2942
2945
}
2943
2946
// Add the default-entry of the original instruction as case-entry.
2944
- CaseBBs.push_back (std::make_pair (elementDecl.get (), SWI.getDefaultBB ()));
2947
+ auto *defaultBB = SWI.getDefaultBB ();
2948
+ CaseBBs.push_back (std::make_pair (elementDecl.get (), defaultBB));
2945
2949
2946
2950
if (isa<SwitchEnumInst>(*SWI)) {
2951
+ if (Fn.hasOwnership ()) {
2952
+ assert (defaultBB->getNumArguments () == 1 );
2953
+ defaultBB->getArgument (0 )->replaceAllUsesWith (SWI.getOperand ());
2954
+ defaultBB->eraseArgument (0 );
2955
+ // TODO: handle non-trivial payloads. The new block argument must be
2956
+ // destroyed. The old default argument may need to be copied. But it may
2957
+ // also be possible to optimize the common case on-the-fly without the
2958
+ // extra copy/destroy.
2959
+ if (elementDecl.get ()->hasAssociatedValues ()) {
2960
+ // Note: this is not really a phi.
2961
+ auto elementTy = SWI.getOperand ()->getType ().getEnumElementType (
2962
+ elementDecl.get (), Fn.getModule (), Fn.getTypeExpansionContext ());
2963
+ defaultBB->createPhiArgument (elementTy, OwnershipKind::None);
2964
+ }
2965
+ }
2947
2966
SILBuilderWithScope (SWI).createSwitchEnum (SWI->getLoc (), SWI.getOperand (),
2948
2967
nullptr , CaseBBs);
2949
2968
} else {
0 commit comments