/// \brief Simplify arithmetic intrinsics with overflow and known identity /// constants such as 0 and 1. /// If this returns a value other than SILValue() then the instruction was /// simplified to a value which doesn't overflow. The overflow case is handled /// in SILCombine. static SILValue simplifyBinaryWithOverflow(BuiltinInst *BI, llvm::Intrinsic::ID ID) { OperandValueArrayRef Args = BI->getArguments(); assert(Args.size() >= 2); const SILValue &Op1 = Args[0]; const SILValue &Op2 = Args[1]; auto *IntOp1 = dyn_cast<IntegerLiteralInst>(Op1); auto *IntOp2 = dyn_cast<IntegerLiteralInst>(Op2); // If both ops are not constants, we cannot do anything. // FIXME: Add cases where we can do something, eg, (x - x) -> 0 if (!IntOp1 && !IntOp2) return SILValue(); // Calculate the result. switch (ID) { default: llvm_unreachable("Invalid case"); case llvm::Intrinsic::sadd_with_overflow: case llvm::Intrinsic::uadd_with_overflow: // 0 + X -> X if (match(Op1, m_Zero())) return Op2; // X + 0 -> X if (match(Op2, m_Zero())) return Op1; return SILValue(); case llvm::Intrinsic::ssub_with_overflow: case llvm::Intrinsic::usub_with_overflow: // X - 0 -> X if (match(Op2, m_Zero())) return Op1; return SILValue(); case llvm::Intrinsic::smul_with_overflow: case llvm::Intrinsic::umul_with_overflow: // 0 * X -> 0 if (match(Op1, m_Zero())) return Op1; // X * 0 -> 0 if (match(Op2, m_Zero())) return Op2; // 1 * X -> X if (match(Op1, m_One())) return Op2; // X * 1 -> X if (match(Op2, m_One())) return Op1; return SILValue(); } return SILValue(); }
/// Like ValueIsPHI but also check if the PHI has no source /// operands, i.e., it was just added. static SILPhiArgument *ValueIsNewPHI(SILValue Val, SILSSAUpdater *Updater) { SILPhiArgument *PHI = ValueIsPHI(Val, Updater); if (PHI) { auto *PhiBB = PHI->getParent(); size_t PhiIdx = PHI->getIndex(); // If all predecessor edges are 'not set' this is a new phi. for (auto *PredBB : PhiBB->getPredecessorBlocks()) { OperandValueArrayRef Edges = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); assert(PhiIdx < Edges.size() && "Not enough edges!"); SILValue V = Edges[PhiIdx]; // Check for the 'not set' sentinel. if (V != Updater->PHISentinel.get()) return nullptr; } return PHI; } return nullptr; }
/// We rotated a loop if it has the following properties. /// /// * It has an exiting header with a conditional branch. /// * It has a preheader (the function will try to create one for critical edges /// from cond_br). /// /// We will rotate at most up to the basic block passed as an argument. /// We will not rotate a loop where the header is equal to the latch except is /// RotateSingleBlockLoops is true. /// /// Note: The code relies on the 'UpTo' basic block to stay within the rotate /// loop for termination. bool swift::rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, bool RotateSingleBlockLoops, SILBasicBlock *UpTo, bool ShouldVerify) { assert(L != nullptr && DT != nullptr && LI != nullptr && "Missing loop information"); auto *Header = L->getHeader(); if (!Header) return false; // We need a preheader - this is also a canonicalization for follow-up // passes. auto *Preheader = L->getLoopPreheader(); if (!Preheader) { LLVM_DEBUG(llvm::dbgs() << *L << " no preheader\n"); LLVM_DEBUG(L->getHeader()->getParent()->dump()); return false; } if (!RotateSingleBlockLoops && (Header == UpTo || isSingleBlockLoop(L))) return false; assert(RotateSingleBlockLoops || L->getBlocks().size() != 1); // Need a conditional branch that guards the entry into the loop. auto *LoopEntryBranch = dyn_cast<CondBranchInst>(Header->getTerminator()); if (!LoopEntryBranch) return false; // The header needs to exit the loop. if (!L->isLoopExiting(Header)) { LLVM_DEBUG(llvm::dbgs() << *L << " not an exiting header\n"); LLVM_DEBUG(L->getHeader()->getParent()->dump()); return false; } // We need a single backedge and the latch must not exit the loop if it is // also the header. auto *Latch = L->getLoopLatch(); if (!Latch) { LLVM_DEBUG(llvm::dbgs() << *L << " no single latch\n"); return false; } // Make sure we can duplicate the header. SmallVector<SILInstruction *, 8> MoveToPreheader; if (!canDuplicateOrMoveToPreheader(L, Preheader, Header, MoveToPreheader)) { LLVM_DEBUG(llvm::dbgs() << *L << " instructions in header preventing rotating\n"); return false; } auto *NewHeader = LoopEntryBranch->getTrueBB(); auto *Exit = LoopEntryBranch->getFalseBB(); if (L->contains(Exit)) std::swap(NewHeader, Exit); assert(L->contains(NewHeader) && !L->contains(Exit) && "Could not find loop header and exit block"); // We don't want to rotate such that we merge two headers of separate loops // into one. This can be turned into an assert again once we have guaranteed // preheader insertions. if (!NewHeader->getSinglePredecessorBlock() && Header != Latch) return false; // Now that we know we can perform the rotation - move the instructions that // need moving. for (auto *Inst : MoveToPreheader) Inst->moveBefore(Preheader->getTerminator()); LLVM_DEBUG(llvm::dbgs() << " Rotating " << *L); // Map the values for the duplicated header block. We are duplicating the // header instructions into the end of the preheader. llvm::DenseMap<ValueBase *, SILValue> ValueMap; // The original 'phi' argument values are just the values coming from the // preheader edge. ArrayRef<SILArgument *> PHIs = Header->getArguments(); OperandValueArrayRef PreheaderArgs = cast<BranchInst>(Preheader->getTerminator())->getArgs(); assert(PHIs.size() == PreheaderArgs.size() && "Basic block arguments and incoming edge mismatch"); // Here we also store the value index to use into the value map (versus // non-argument values where the operand use decides which value index to // use). for (unsigned Idx = 0, E = PHIs.size(); Idx != E; ++Idx) ValueMap[PHIs[Idx]] = PreheaderArgs[Idx]; // The other instructions are just cloned to the preheader. TermInst *PreheaderBranch = Preheader->getTerminator(); for (auto &Inst : *Header) { if (SILInstruction *cloned = Inst.clone(PreheaderBranch)) { mapOperands(cloned, ValueMap); // The actual operand will sort out which result idx to use. auto instResults = Inst.getResults(); auto clonedResults = cloned->getResults(); assert(instResults.size() == clonedResults.size()); for (auto i : indices(instResults)) ValueMap[instResults[i]] = clonedResults[i]; } } PreheaderBranch->dropAllReferences(); PreheaderBranch->eraseFromParent(); // If there were any uses of instructions in the duplicated loop entry check // block rewrite them using the ssa updater. rewriteNewLoopEntryCheckBlock(Header, Preheader, ValueMap); L->moveToHeader(NewHeader); // Now the original preheader dominates all of headers children and the // original latch dominates the header. updateDomTree(DT, Preheader, Latch, Header); assert(DT->getNode(NewHeader)->getIDom() == DT->getNode(Preheader)); assert(!DT->dominates(Header, Exit) || DT->getNode(Exit)->getIDom() == DT->getNode(Preheader)); assert(DT->getNode(Header)->getIDom() == DT->getNode(Latch) || ((Header == Latch) && DT->getNode(Header)->getIDom() == DT->getNode(Preheader))); // Beautify the IR. Move the old header to after the old latch as it is now // the latch. Header->moveAfter(Latch); // Merge the old latch with the old header if possible. mergeBasicBlockWithSuccessor(Latch, DT, LI); // Create a new preheader. splitIfCriticalEdge(Preheader, NewHeader, DT, LI); if (ShouldVerify) { DT->verify(); LI->verify(); Latch->getParent()->verify(); } LLVM_DEBUG(llvm::dbgs() << " to " << *L); LLVM_DEBUG(L->getHeader()->getParent()->dump()); return true; }
/// \brief Changes the edge value between a branch and destination basic block /// at the specified index. Changes all edges from \p Branch to \p Dest to carry /// the value. /// /// \param Branch The branch to modify. /// \param Dest The destination of the edge. /// \param Idx The index of the argument to modify. /// \param Val The new value to use. /// \return The new branch. Deletes the old one. /// Changes the edge value between a branch and destination basic block at the /// specified index. TermInst *swift::changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, size_t Idx, SILValue Val) { SILBuilderWithScope Builder(Branch); if (CondBranchInst *CBI = dyn_cast<CondBranchInst>(Branch)) { SmallVector<SILValue, 8> TrueArgs; SmallVector<SILValue, 8> FalseArgs; OperandValueArrayRef OldTrueArgs = CBI->getTrueArgs(); bool BranchOnTrue = CBI->getTrueBB() == Dest; assert((!BranchOnTrue || Idx < OldTrueArgs.size()) && "Not enough edges"); // Copy the edge values overwriting the edge at Idx. for (unsigned i = 0, e = OldTrueArgs.size(); i != e; ++i) { if (BranchOnTrue && Idx == i) TrueArgs.push_back(Val); else TrueArgs.push_back(OldTrueArgs[i]); } assert(TrueArgs.size() == CBI->getTrueBB()->getNumBBArg() && "Destination block's number of arguments must match"); OperandValueArrayRef OldFalseArgs = CBI->getFalseArgs(); bool BranchOnFalse = CBI->getFalseBB() == Dest; assert((!BranchOnFalse || Idx < OldFalseArgs.size()) && "Not enough edges"); // Copy the edge values overwriting the edge at Idx. for (unsigned i = 0, e = OldFalseArgs.size(); i != e; ++i) { if (BranchOnFalse && Idx == i) FalseArgs.push_back(Val); else FalseArgs.push_back(OldFalseArgs[i]); } assert(FalseArgs.size() == CBI->getFalseBB()->getNumBBArg() && "Destination block's number of arguments must match"); CBI = Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, CBI->getFalseBB(), FalseArgs); Branch->dropAllReferences(); Branch->eraseFromParent(); return CBI; } if (BranchInst *BI = dyn_cast<BranchInst>(Branch)) { SmallVector<SILValue, 8> Args; assert(Idx < BI->getNumArgs() && "Not enough edges"); OperandValueArrayRef OldArgs = BI->getArgs(); // Copy the edge values overwriting the edge at Idx. for (unsigned i = 0, e = OldArgs.size(); i != e; ++i) { if (Idx == i) Args.push_back(Val); else Args.push_back(OldArgs[i]); } assert(Args.size() == Dest->getNumBBArg()); BI = Builder.createBranch(BI->getLoc(), BI->getDestBB(), Args); Branch->dropAllReferences(); Branch->eraseFromParent(); return BI; } llvm_unreachable("Unhandled terminator leading to merge block"); }
SILValue getValueForBlock(size_t Idx, SILBasicBlock *BB, TermInst *TI) { OperandValueArrayRef Args = getEdgeValuesForTerminator(TI, BB); assert(Idx < Args.size() && "Not enough values on incoming edge"); return Args[Idx]; }
SILInstruction * SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI, ConvertFunctionInst *CFI) { // We only handle simplification of static function references. If we don't // have one, bail. FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(CFI->getOperand()); if (!FRI) return nullptr; // Grab our relevant callee types... CanSILFunctionType SubstCalleeTy = AI.getSubstCalleeType(); auto ConvertCalleeTy = CFI->getOperand()->getType().castTo<SILFunctionType>(); // ... and make sure they have no unsubstituted generics. If they do, bail. if (SubstCalleeTy->hasArchetype() || ConvertCalleeTy->hasArchetype()) return nullptr; // Ok, we can now perform our transformation. Grab AI's operands and the // relevant types from the ConvertFunction function type and AI. Builder.setCurrentDebugScope(AI.getDebugScope()); OperandValueArrayRef Ops = AI.getArgumentsWithoutIndirectResults(); auto OldOpTypes = SubstCalleeTy->getParameterSILTypes(); auto NewOpTypes = ConvertCalleeTy->getParameterSILTypes(); assert(Ops.size() == OldOpTypes.size() && "Ops and op types must have same size."); assert(Ops.size() == NewOpTypes.size() && "Ops and op types must have same size."); llvm::SmallVector<SILValue, 8> Args; for (unsigned i = 0, e = Ops.size(); i != e; ++i) { SILValue Op = Ops[i]; SILType OldOpType = OldOpTypes[i]; SILType NewOpType = NewOpTypes[i]; // Convert function takes refs to refs, address to addresses, and leaves // other types alone. if (OldOpType.isAddress()) { assert(NewOpType.isAddress() && "Addresses should map to addresses."); auto UAC = Builder.createUncheckedAddrCast(AI.getLoc(), Op, NewOpType); Args.push_back(UAC); } else if (OldOpType.isHeapObjectReferenceType()) { assert(NewOpType.isHeapObjectReferenceType() && "refs should map to refs."); auto URC = Builder.createUncheckedRefCast(AI.getLoc(), Op, NewOpType); Args.push_back(URC); } else { Args.push_back(Op); } } SILType CCSILTy = SILType::getPrimitiveObjectType(ConvertCalleeTy); // Create the new apply inst. SILInstruction *NAI; if (auto *TAI = dyn_cast<TryApplyInst>(AI)) NAI = Builder.createTryApply(AI.getLoc(), FRI, CCSILTy, ArrayRef<Substitution>(), Args, TAI->getNormalBB(), TAI->getErrorBB()); else NAI = Builder.createApply(AI.getLoc(), FRI, CCSILTy, ConvertCalleeTy->getSILResult(), ArrayRef<Substitution>(), Args, cast<ApplyInst>(AI)->isNonThrowing()); return NAI; }
/// \brief Fold arithmetic intrinsics with overflow. static SILInstruction * constantFoldBinaryWithOverflow(BuiltinInst *BI, llvm::Intrinsic::ID ID, bool ReportOverflow, Optional<bool> &ResultsInError) { OperandValueArrayRef Args = BI->getArguments(); assert(Args.size() >= 2); auto *Op1 = dyn_cast<IntegerLiteralInst>(Args[0]); auto *Op2 = dyn_cast<IntegerLiteralInst>(Args[1]); // If either Op1 or Op2 is not a literal, we cannot do anything. if (!Op1 || !Op2) return nullptr; // Calculate the result. APInt LHSInt = Op1->getValue(); APInt RHSInt = Op2->getValue(); bool Overflow; APInt Res = constantFoldBinaryWithOverflow(LHSInt, RHSInt, Overflow, ID); // If we can statically determine that the operation overflows, // warn about it if warnings are not disabled by ResultsInError being null. if (ResultsInError.hasValue() && Overflow && ReportOverflow) { // Try to infer the type of the constant expression that the user operates // on. If the intrinsic was lowered from a call to a function that takes // two arguments of the same type, use the type of the LHS argument. // This would detect '+'/'+=' and such. Type OpType; SILLocation Loc = BI->getLoc(); const ApplyExpr *CE = Loc.getAsASTNode<ApplyExpr>(); SourceRange LHSRange, RHSRange; if (CE) { const auto *Args = dyn_cast_or_null<TupleExpr>(CE->getArg()); if (Args && Args->getNumElements() == 2) { // Look through inout types in order to handle += well. CanType LHSTy = Args->getElement(0)->getType()->getInOutObjectType()-> getCanonicalType(); CanType RHSTy = Args->getElement(1)->getType()->getCanonicalType(); if (LHSTy == RHSTy) OpType = Args->getElement(1)->getType(); LHSRange = Args->getElement(0)->getSourceRange(); RHSRange = Args->getElement(1)->getSourceRange(); } } bool Signed = false; StringRef Operator = "+"; switch (ID) { default: llvm_unreachable("Invalid case"); case llvm::Intrinsic::sadd_with_overflow: Signed = true; break; case llvm::Intrinsic::uadd_with_overflow: break; case llvm::Intrinsic::ssub_with_overflow: Operator = "-"; Signed = true; break; case llvm::Intrinsic::usub_with_overflow: Operator = "-"; break; case llvm::Intrinsic::smul_with_overflow: Operator = "*"; Signed = true; break; case llvm::Intrinsic::umul_with_overflow: Operator = "*"; break; } if (!OpType.isNull()) { diagnose(BI->getModule().getASTContext(), Loc.getSourceLoc(), diag::arithmetic_operation_overflow, LHSInt.toString(/*Radix*/ 10, Signed), Operator, RHSInt.toString(/*Radix*/ 10, Signed), OpType).highlight(LHSRange).highlight(RHSRange); } else { // If we cannot get the type info in an expected way, describe the type. diagnose(BI->getModule().getASTContext(), Loc.getSourceLoc(), diag::arithmetic_operation_overflow_generic_type, LHSInt.toString(/*Radix*/ 10, Signed), Operator, RHSInt.toString(/*Radix*/ 10, Signed), Signed, LHSInt.getBitWidth()).highlight(LHSRange).highlight(RHSRange); } ResultsInError = Optional<bool>(true); } return constructResultWithOverflowTuple(BI, Res, Overflow); }