void FunctionSignatureTransform::ArgumentExplosionFinalizeOptimizedFunction() { SILBasicBlock *BB = &*NewF->begin(); SILBuilder Builder(BB->begin()); Builder.setCurrentDebugScope(BB->getParent()->getDebugScope()); unsigned TotalArgIndex = 0; for (ArgumentDescriptor &AD : ArgumentDescList) { // Simply continue if do not explode. if (!AD.Explode) { AIM[TotalArgIndex] = AD.Index; TotalArgIndex ++; continue; } // OK, we need to explode this argument. unsigned ArgOffset = ++TotalArgIndex; unsigned OldArgIndex = ArgOffset - 1; llvm::SmallVector<SILValue, 8> LeafValues; // We do this in the same order as leaf types since ProjTree expects that the // order of leaf values matches the order of leaf types. llvm::SmallVector<const ProjectionTreeNode*, 8> LeafNodes; AD.ProjTree.getLeafNodes(LeafNodes); for (auto Node : LeafNodes) { LeafValues.push_back(BB->insertBBArg(ArgOffset++, Node->getType(), BB->getBBArg(OldArgIndex)->getDecl())); AIM[TotalArgIndex - 1] = AD.Index; TotalArgIndex ++; } // Then go through the projection tree constructing aggregates and replacing // uses. AD.ProjTree.replaceValueUsesWithLeafUses(Builder, BB->getParent()->getLocation(), LeafValues); // We ignored debugvalue uses when we constructed the new arguments, in order // to preserve as much information as possible, we construct a new value for // OrigArg from the leaf values and use that in place of the OrigArg. SILValue NewOrigArgValue = AD.ProjTree.computeExplodedArgumentValue(Builder, BB->getParent()->getLocation(), LeafValues); // Replace all uses of the original arg with the new value. SILArgument *OrigArg = BB->getBBArg(OldArgIndex); OrigArg->replaceAllUsesWith(NewOrigArgValue); // Now erase the old argument since it does not have any uses. We also // decrement ArgOffset since we have one less argument now. BB->eraseBBArg(OldArgIndex); TotalArgIndex --; } }
SILInstruction *SILCombiner::visitTryApplyInst(TryApplyInst *AI) { // apply{partial_apply(x,y)}(z) -> apply(z,x,y) is triggered // from visitPartialApplyInst(), so bail here. if (isa<PartialApplyInst>(AI->getCallee())) return nullptr; if (auto *CFI = dyn_cast<ConvertFunctionInst>(AI->getCallee())) { return optimizeApplyOfConvertFunctionInst(AI, CFI); } // Optimize readonly functions with no meaningful users. SILFunction *Fn = AI->getReferencedFunction(); if (Fn && Fn->getEffectsKind() < EffectsKind::ReadWrite) { UserListTy Users; if (isTryApplyResultNotUsed(Users, AI)) { SILBasicBlock *BB = AI->getParent(); SILBasicBlock *NormalBB = AI->getNormalBB(); SILBasicBlock *ErrorBB = AI->getErrorBB(); SILLocation Loc = AI->getLoc(); Builder.setInsertionPoint(BB); Builder.setCurrentDebugScope(AI->getDebugScope()); eraseApply(AI, Users); // Replace the try_apply with a cond_br false, which will be removed by // SimplifyCFG. We don't want to modify the CFG in SILCombine. auto *TrueLit = Builder.createIntegerLiteral(Loc, SILType::getBuiltinIntegerType(1, Builder.getASTContext()), 0); Builder.createCondBranch(Loc, TrueLit, NormalBB, ErrorBB); NormalBB->eraseBBArg(0); ErrorBB->eraseBBArg(0); return nullptr; } // We found a user that we can't handle. } // (try_apply (thin_to_thick_function f)) to (try_apply f) if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(AI->getCallee())) { // TODO: Handle substitutions and indirect results if (AI->hasSubstitutions() || AI->hasIndirectResults()) return nullptr; SmallVector<SILValue, 4> Arguments; for (auto &Op : AI->getArgumentOperands()) { Arguments.push_back(Op.get()); } // The type of the substitution is the source type of the thin to thick // instruction. SILType substTy = TTTFI->getOperand()->getType(); auto *NewAI = Builder.createTryApply(AI->getLoc(), TTTFI->getOperand(), substTy, AI->getSubstitutions(), Arguments, AI->getNormalBB(), AI->getErrorBB()); return NewAI; } // (apply (witness_method)) -> propagate information about // a concrete type from init_existential_addr or init_existential_ref. if (auto *WMI = dyn_cast<WitnessMethodInst>(AI->getCallee())) { propagateConcreteTypeOfInitExistential(AI, WMI); return nullptr; } // (apply (function_ref method_from_protocol_extension)) -> // propagate information about a concrete type from init_existential_addr or // init_existential_ref. if (isa<FunctionRefInst>(AI->getCallee())) { if (propagateConcreteTypeOfInitExistential(AI)) { return nullptr; } } return nullptr; }