static void mangleSubstitution(Mangler &M, Substitution Sub) { M.mangleType(Sub.getReplacement()->getCanonicalType(), 0); for (auto C : Sub.getConformances()) { if (C.isAbstract()) return; M.mangleProtocolConformance(C.getConcrete()); } }
static void mangleSubstitution(Mangler &M, Substitution Sub) { M.mangleType(Sub.getReplacement()->getCanonicalType(), ResilienceExpansion::Minimal, 0); for (auto C : Sub.getConformances()) { if (!C) return; M.mangleProtocolConformance(C); } }
SILInstruction *SILCombiner::visitBuiltinInst(BuiltinInst *I) { if (I->getBuiltinInfo().ID == BuiltinValueKind::CanBeObjCClass) return optimizeBuiltinCanBeObjCClass(I); if (I->getBuiltinInfo().ID == BuiltinValueKind::TakeArrayFrontToBack || I->getBuiltinInfo().ID == BuiltinValueKind::TakeArrayBackToFront || I->getBuiltinInfo().ID == BuiltinValueKind::CopyArray) return optimizeBuiltinArrayOperation(I, Builder); if (I->getNumOperands() >= 2 && I->getOperand(0) == I->getOperand(1)) { // It's a builtin which has the same value in its first and second operand. auto *Replacement = optimizeBuiltinWithSameOperands(Builder, I, this); if (Replacement) return Replacement; } // Optimize this case for unsigned and equality comparisons: // cmp_*_T . (zext U->T x, zext U->T y) // => cmp_*_T (x, y) switch (I->getBuiltinInfo().ID) { case BuiltinValueKind::ICMP_EQ: case BuiltinValueKind::ICMP_NE: case BuiltinValueKind::ICMP_ULE: case BuiltinValueKind::ICMP_ULT: case BuiltinValueKind::ICMP_UGE: case BuiltinValueKind::ICMP_UGT: { SILValue LCast, RCast; if (match(I->getArguments()[0], m_ApplyInst(BuiltinValueKind::ZExtOrBitCast, m_SILValue(LCast))) && match(I->getArguments()[1], m_ApplyInst(BuiltinValueKind::ZExtOrBitCast, m_SILValue(RCast))) && LCast->getType() == RCast->getType()) { auto *NewCmp = Builder.createBuiltinBinaryFunction( I->getLoc(), getBuiltinName(I->getBuiltinInfo().ID), LCast->getType(), I->getType(), {LCast, RCast}); I->replaceAllUsesWith(NewCmp); replaceInstUsesWith(*I, NewCmp); return eraseInstFromFunction(*I); } break; } case BuiltinValueKind::And: return optimizeBitOp(I, [](APInt &left, const APInt &right) { left &= right; } /* combine */, [](const APInt &i) -> bool { return i.isAllOnesValue(); } /* isNeutral */, [](const APInt &i) -> bool { return i.isMinValue(); } /* isZero */, Builder, this); case BuiltinValueKind::Or: return optimizeBitOp(I, [](APInt &left, const APInt &right) { left |= right; } /* combine */, [](const APInt &i) -> bool { return i.isMinValue(); } /* isNeutral */, [](const APInt &i) -> bool { return i.isAllOnesValue(); } /* isZero */, Builder, this); case BuiltinValueKind::Xor: return optimizeBitOp(I, [](APInt &left, const APInt &right) { left ^= right; } /* combine */, [](const APInt &i) -> bool { return i.isMinValue(); } /* isNeutral */, [](const APInt &i) -> bool { return false; } /* isZero */, Builder, this); case BuiltinValueKind::DestroyArray: { ArrayRef<Substitution> Substs = I->getSubstitutions(); // Check if the element type is a trivial type. if (Substs.size() == 1) { Substitution Subst = Substs[0]; Type ElemType = Subst.getReplacement(); if (ElemType->isCanonical() && ElemType->isLegalSILType()) { SILType SILElemTy = SILType::getPrimitiveObjectType(CanType(ElemType)); // Destroying an array of trivial types is a no-op. if (SILElemTy.isTrivial(I->getModule())) return eraseInstFromFunction(*I); } } break; } default: break; } if (I->getBuiltinInfo().ID == BuiltinValueKind::ICMP_EQ) return optimizeBuiltinCompareEq(I, /*Negate Eq result*/ false); if (I->getBuiltinInfo().ID == BuiltinValueKind::ICMP_NE) return optimizeBuiltinCompareEq(I, /*Negate Eq result*/ true); // Optimize sub(ptrtoint(index_raw_pointer(v, x)), ptrtoint(v)) -> x. BuiltinInst *Bytes2; IndexRawPointerInst *Indexraw; if (I->getNumOperands() == 2 && match(I, m_BuiltinInst(BuiltinValueKind::Sub, m_BuiltinInst(BuiltinValueKind::PtrToInt, m_IndexRawPointerInst(Indexraw)), m_BuiltinInst(Bytes2)))) { if (match(Bytes2, m_BuiltinInst(BuiltinValueKind::PtrToInt, m_ValueBase()))) { if (Indexraw->getOperand(0) == Bytes2->getOperand(0) && Indexraw->getOperand(1)->getType() == I->getType()) { replaceInstUsesWith(*I, Indexraw->getOperand(1)); return eraseInstFromFunction(*I); } } } // Canonicalize multiplication by a stride to be such that the stride is // always the second argument. if (I->getNumOperands() != 3) return nullptr; if (match(I, m_ApplyInst(BuiltinValueKind::SMulOver, m_ApplyInst(BuiltinValueKind::Strideof), m_ValueBase(), m_IntegerLiteralInst())) || match(I, m_ApplyInst(BuiltinValueKind::SMulOver, m_ApplyInst(BuiltinValueKind::StrideofNonZero), m_ValueBase(), m_IntegerLiteralInst()))) { I->swapOperands(0, 1); return I; } return nullptr; }