本文整理汇总了C++中SmallVectorImpl::back方法的典型用法代码示例。如果您正苦于以下问题:C++ SmallVectorImpl::back方法的具体用法?C++ SmallVectorImpl::back怎么用?C++ SmallVectorImpl::back使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SmallVectorImpl
的用法示例。
在下文中一共展示了SmallVectorImpl::back方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: MaybeRemoveCommaBeforeVaArgs
bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro,
unsigned MacroArgNo, Preprocessor &PP) {
// Is the macro argument __VA_ARGS__?
if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1)
return false;
// In Microsoft-compatibility mode, a comma is removed in the expansion
// of " ... , __VA_ARGS__ " if __VA_ARGS__ is empty. This extension is
// not supported by gcc.
if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)
return false;
// GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if
// __VA_ARGS__ is empty, but not in strict C99 mode where there are no
// named arguments, where it remains. In all other modes, including C99
// with GNU extensions, it is removed regardless of named arguments.
// Microsoft also appears to support this extension, unofficially.
if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode
&& Macro->getNumArgs() < 2)
return false;
// Is a comma available to be removed?
if (ResultToks.empty() || !ResultToks.back().is(tok::comma))
return false;
// Issue an extension diagnostic for the paste operator.
if (HasPasteOperator)
PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
// Remove the comma.
ResultToks.pop_back();
if (!ResultToks.empty()) {
// If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"),
// then removal of the comma should produce a placemarker token (in C99
// terms) which we model by popping off the previous ##, giving us a plain
// "X" when __VA_ARGS__ is empty.
if (ResultToks.back().is(tok::hashhash))
ResultToks.pop_back();
// Remember that this comma was elided.
ResultToks.back().setFlag(Token::CommaAfterElided);
}
// Never add a space, even if the comma, ##, or arg had a space.
NextTokGetsSpace = false;
return true;
}
示例2: addCommentToList
static void addCommentToList(SmallVectorImpl<SingleRawComment> &Comments,
const SingleRawComment &SRC) {
// TODO: consider producing warnings when we decide not to merge comments.
if (SRC.isOrdinary()) {
// Skip gyb comments that are line number markers.
if (SRC.RawText.startswith("// ###"))
return;
Comments.clear();
return;
}
// If this is the first documentation comment, save it (because there isn't
// anything to merge it with).
if (Comments.empty()) {
Comments.push_back(SRC);
return;
}
auto &Last = Comments.back();
// Merge comments if they are on same or consecutive lines.
if (Last.EndLine + 1 < SRC.StartLine) {
Comments.clear();
return;
}
Comments.push_back(SRC);
}
示例3: allPatternsRange
/// Parse function arguments.
/// func-arguments:
/// curried-arguments | selector-arguments
/// curried-arguments:
/// parameter-clause+
/// selector-arguments:
/// '(' selector-element ')' (identifier '(' selector-element ')')+
/// selector-element:
/// identifier '(' pattern-atom (':' type)? ('=' expr)? ')'
///
ParserStatus
Parser::parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces,
SmallVectorImpl<ParameterList*> &BodyParams,
ParameterContextKind paramContext,
DefaultArgumentInfo &DefaultArgs) {
// Parse parameter-clauses.
ParserStatus status;
bool isFirstParameterClause = true;
unsigned FirstBodyPatternIndex = BodyParams.size();
while (Tok.is(tok::l_paren)) {
SmallVector<ParsedParameter, 4> params;
SourceLoc leftParenLoc, rightParenLoc;
// Parse the parameter clause.
status |= parseParameterClause(leftParenLoc, params, rightParenLoc,
&DefaultArgs, paramContext);
// Turn the parameter clause into argument and body patterns.
auto pattern = mapParsedParameters(*this, leftParenLoc, params,
rightParenLoc,
isFirstParameterClause,
isFirstParameterClause ? &NamePieces
: nullptr,
paramContext);
BodyParams.push_back(pattern);
isFirstParameterClause = false;
paramContext = ParameterContextKind::Curried;
}
// If the decl uses currying syntax, complain that that syntax has gone away.
if (BodyParams.size() - FirstBodyPatternIndex > 1) {
SourceRange allPatternsRange(
BodyParams[FirstBodyPatternIndex]->getStartLoc(),
BodyParams.back()->getEndLoc());
auto diag = diagnose(allPatternsRange.Start,
diag::parameter_curry_syntax_removed);
diag.highlight(allPatternsRange);
bool seenArg = false;
for (unsigned i = FirstBodyPatternIndex; i < BodyParams.size() - 1; i++) {
// Replace ")(" with ", ", so "(x: Int)(y: Int)" becomes
// "(x: Int, y: Int)". But just delete them if they're not actually
// separating any arguments, e.g. in "()(y: Int)".
StringRef replacement(", ");
auto *leftParamList = BodyParams[i];
auto *rightParamList = BodyParams[i + 1];
if (leftParamList->size() != 0)
seenArg = true;
if (!seenArg || rightParamList->size() == 0)
replacement = "";
diag.fixItReplace(SourceRange(leftParamList->getEndLoc(),
rightParamList->getStartLoc()),
replacement);
}
}
return status;
}
示例4: findComponents
bool RenameIndependentSubregs::findComponents(IntEqClasses &Classes,
SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> &SubRangeInfos,
LiveInterval &LI) const {
// First step: Create connected components for the VNInfos inside the
// subranges and count the global number of such components.
unsigned NumComponents = 0;
for (LiveInterval::SubRange &SR : LI.subranges()) {
SubRangeInfos.push_back(SubRangeInfo(*LIS, SR, NumComponents));
ConnectedVNInfoEqClasses &ConEQ = SubRangeInfos.back().ConEQ;
unsigned NumSubComponents = ConEQ.Classify(SR);
NumComponents += NumSubComponents;
}
// Shortcut: With only 1 subrange, the normal separate component tests are
// enough and we do not need to perform the union-find on the subregister
// segments.
if (SubRangeInfos.size() < 2)
return false;
// Next step: Build union-find structure over all subranges and merge classes
// across subranges when they are affected by the same MachineOperand.
const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo();
Classes.grow(NumComponents);
unsigned Reg = LI.reg;
for (const MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) {
if (!MO.isDef() && !MO.readsReg())
continue;
unsigned SubRegIdx = MO.getSubReg();
LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
unsigned MergedID = ~0u;
for (RenameIndependentSubregs::SubRangeInfo &SRInfo : SubRangeInfos) {
const LiveInterval::SubRange &SR = *SRInfo.SR;
if ((SR.LaneMask & LaneMask) == 0)
continue;
SlotIndex Pos = LIS->getInstructionIndex(*MO.getParent());
Pos = MO.isDef() ? Pos.getRegSlot(MO.isEarlyClobber())
: Pos.getBaseIndex();
const VNInfo *VNI = SR.getVNInfoAt(Pos);
if (VNI == nullptr)
continue;
// Map to local representant ID.
unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI);
// Global ID
unsigned ID = LocalID + SRInfo.Index;
// Merge other sets
MergedID = MergedID == ~0u ? ID : Classes.join(MergedID, ID);
}
}
// Early exit if we ended up with a single equivalence class.
Classes.compress();
unsigned NumClasses = Classes.getNumClasses();
return NumClasses > 1;
}
示例5: columnToByte
/// This function takes a raw source line and produces a mapping from columns
/// to the byte of the source line that produced the character displaying at
/// that column. This is the inverse of the mapping produced by byteToColumn()
///
/// The last element in the array is the number of bytes in the source string
///
/// example: (given a tabstop of 8)
///
/// "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
///
/// (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
/// display)
static void columnToByte(StringRef SourceLine, unsigned TabStop,
SmallVectorImpl<int> &out) {
out.clear();
if (SourceLine.empty()) {
out.resize(1u, 0);
return;
}
int columns = 0;
size_t i = 0;
while (i<SourceLine.size()) {
out.resize(columns+1, -1);
out.back() = i;
std::pair<SmallString<16>,bool> res
= printableTextForNextCharacter(SourceLine, &i, TabStop);
columns += llvm::sys::locale::columnWidth(res.first);
}
out.resize(columns+1, -1);
out.back() = i;
}
示例6: ParseFunctionArgs
static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
SmallVectorImpl<unsigned> &Out) {
unsigned CurrentArgIndex = ~0U;
for (unsigned i = 0, e = Args.size(); i != e; i++) {
if (CurrentArgIndex == Args[i].OrigArgIndex) {
Out.back()++;
} else {
Out.push_back(1);
CurrentArgIndex++;
}
}
}
示例7: stringifyVAOPTContents
void TokenLexer::stringifyVAOPTContents(
SmallVectorImpl<Token> &ResultToks, const VAOptExpansionContext &VCtx,
const SourceLocation VAOPTClosingParenLoc) {
const int NumToksPriorToVAOpt = VCtx.getNumberOfTokensPriorToVAOpt();
const unsigned int NumVAOptTokens = ResultToks.size() - NumToksPriorToVAOpt;
Token *const VAOPTTokens =
NumVAOptTokens ? &ResultToks[NumToksPriorToVAOpt] : nullptr;
SmallVector<Token, 64> ConcatenatedVAOPTResultToks;
// FIXME: Should we keep track within VCtx that we did or didnot
// encounter pasting - and only then perform this loop.
// Perform token pasting (concatenation) prior to stringization.
for (unsigned int CurTokenIdx = 0; CurTokenIdx != NumVAOptTokens;
++CurTokenIdx) {
if (VAOPTTokens[CurTokenIdx].is(tok::hashhash)) {
assert(CurTokenIdx != 0 &&
"Can not have __VAOPT__ contents begin with a ##");
Token &LHS = VAOPTTokens[CurTokenIdx - 1];
pasteTokens(LHS, llvm::makeArrayRef(VAOPTTokens, NumVAOptTokens),
CurTokenIdx);
// Replace the token prior to the first ## in this iteration.
ConcatenatedVAOPTResultToks.back() = LHS;
if (CurTokenIdx == NumVAOptTokens)
break;
}
ConcatenatedVAOPTResultToks.push_back(VAOPTTokens[CurTokenIdx]);
}
ConcatenatedVAOPTResultToks.push_back(VCtx.getEOFTok());
// Get the SourceLocation that represents the start location within
// the macro definition that marks where this string is substituted
// into: i.e. the __VA_OPT__ and the ')' within the spelling of the
// macro definition, and use it to indicate that the stringified token
// was generated from that location.
const SourceLocation ExpansionLocStartWithinMacro =
getExpansionLocForMacroDefLoc(VCtx.getVAOptLoc());
const SourceLocation ExpansionLocEndWithinMacro =
getExpansionLocForMacroDefLoc(VAOPTClosingParenLoc);
Token StringifiedVAOPT = MacroArgs::StringifyArgument(
&ConcatenatedVAOPTResultToks[0], PP, VCtx.hasCharifyBefore() /*Charify*/,
ExpansionLocStartWithinMacro, ExpansionLocEndWithinMacro);
if (VCtx.getLeadingSpaceForStringifiedToken())
StringifiedVAOPT.setFlag(Token::LeadingSpace);
StringifiedVAOPT.setFlag(Token::StringifiedInMacro);
// Resize (shrink) the token stream to just capture this stringified token.
ResultToks.resize(NumToksPriorToVAOpt + 1);
ResultToks.back() = StringifiedVAOPT;
}
示例8: ComputeValueVTs
void AArch64CallLowering::splitToValueTypes(
const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL, MachineRegisterInfo &MRI, CallingConv::ID CallConv,
const SplitArgTy &PerformArgSplit) const {
const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
LLVMContext &Ctx = OrigArg.Ty->getContext();
if (OrigArg.Ty->isVoidTy())
return;
SmallVector<EVT, 4> SplitVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
if (SplitVTs.size() == 1) {
// No splitting to do, but we want to replace the original type (e.g. [1 x
// double] -> double).
SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx),
OrigArg.Flags, OrigArg.IsFixed);
return;
}
unsigned FirstRegIdx = SplitArgs.size();
bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters(
OrigArg.Ty, CallConv, false);
for (auto SplitVT : SplitVTs) {
Type *SplitTy = SplitVT.getTypeForEVT(Ctx);
SplitArgs.push_back(
ArgInfo{MRI.createGenericVirtualRegister(getLLTForType(*SplitTy, DL)),
SplitTy, OrigArg.Flags, OrigArg.IsFixed});
if (NeedsRegBlock)
SplitArgs.back().Flags.setInConsecutiveRegs();
}
SplitArgs.back().Flags.setInConsecutiveRegsLast();
for (unsigned i = 0; i < Offsets.size(); ++i)
PerformArgSplit(SplitArgs[FirstRegIdx + i].Reg, Offsets[i] * 8);
}
示例9: UpdatePhysRegDefs
void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI,
SmallVectorImpl<unsigned> &Defs) {
while (!Defs.empty()) {
unsigned Reg = Defs.back();
Defs.pop_back();
for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
SubRegs.isValid(); ++SubRegs) {
unsigned SubReg = *SubRegs;
PhysRegDef[SubReg] = MI;
PhysRegUse[SubReg] = nullptr;
}
}
}
示例10: dropRegDescribedVar
// \brief Update the register that describes location of @Var in @RegVars map.
static void
updateRegForVariable(RegDescribedVarsMap &RegVars, const MDNode *Var,
const SmallVectorImpl<const MachineInstr *> &VarHistory,
const MachineInstr &MI) {
if (!VarHistory.empty()) {
const MachineInstr &Prev = *VarHistory.back();
// Check if Var is currently described by a register by instruction in the
// same basic block.
if (Prev.isDebugValue() && Prev.getDebugVariable() == Var &&
Prev.getParent() == MI.getParent()) {
if (unsigned PrevReg = isDescribedByReg(Prev))
dropRegDescribedVar(RegVars, PrevReg, Var);
}
}
assert(MI.getDebugVariable() == Var);
if (unsigned MIReg = isDescribedByReg(MI))
addRegDescribedVar(RegVars, MIReg, Var);
}
示例11:
/// \brief Find ambiguity among base classes.
static void
detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
if ((Class->Flags & MSRTTIClass::IsVirtual) &&
!VirtualBases.insert(Class->RD)) {
Class = MSRTTIClass::getNextChild(Class);
continue;
}
if (!UniqueBases.insert(Class->RD))
AmbiguousBases.insert(Class->RD);
Class++;
}
if (AmbiguousBases.empty())
return;
for (MSRTTIClass &Class : Classes)
if (AmbiguousBases.count(Class.RD))
Class.Flags |= MSRTTIClass::IsAmbiguous;
}
示例12: assert
/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke
/// has a try-range containing the call, a non-zero landing pad, and an
/// appropriate action. The entry for an ordinary call has a try-range
/// containing the call and zero for the landing pad and the action. Calls
/// marked 'nounwind' have no entry and must not be contained in the try-range
/// of any entry - they form gaps in the table. Entries must be ordered by
/// try-range address.
void DwarfException::
ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
const RangeMapType &PadMap,
const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
const SmallVectorImpl<unsigned> &FirstActions) {
// The end label of the previous invoke or nounwind try-range.
MCSymbol *LastLabel = 0;
// Whether there is a potentially throwing instruction (currently this means
// an ordinary call) between the end of the previous try-range and now.
bool SawPotentiallyThrowing = false;
// Whether the last CallSite entry was for an invoke.
bool PreviousIsInvoke = false;
// Visit all instructions in order of address.
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
MI != E; ++MI) {
if (!MI->isLabel()) {
if (MI->isCall())
SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI);
continue;
}
// End of the previous try-range?
MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
if (BeginLabel == LastLabel)
SawPotentiallyThrowing = false;
// Beginning of a new try-range?
RangeMapType::const_iterator L = PadMap.find(BeginLabel);
if (L == PadMap.end())
// Nope, it was just some random label.
continue;
const PadRange &P = L->second;
const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
"Inconsistent landing pad map!");
// For Dwarf exception handling (SjLj handling doesn't use this). If some
// instruction between the previous try-range and this one may throw,
// create a call-site entry with no landing pad for the region between the
// try-ranges.
if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) {
CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 };
CallSites.push_back(Site);
PreviousIsInvoke = false;
}
LastLabel = LandingPad->EndLabels[P.RangeIndex];
assert(BeginLabel && LastLabel && "Invalid landing pad!");
if (!LandingPad->LandingPadLabel) {
// Create a gap.
PreviousIsInvoke = false;
} else {
// This try-range is for an invoke.
CallSiteEntry Site = {
BeginLabel,
LastLabel,
LandingPad->LandingPadLabel,
FirstActions[P.PadIndex]
};
// Try to merge with the previous call-site. SJLJ doesn't do this
if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) {
CallSiteEntry &Prev = CallSites.back();
if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
// Extend the range of the previous entry.
Prev.EndLabel = Site.EndLabel;
continue;
}
}
// Otherwise, create a new call-site.
if (Asm->MAI->isExceptionHandlingDwarf())
CallSites.push_back(Site);
else {
// SjLj EH must maintain the call sites in the order assigned
// to them by the SjLjPrepare pass.
unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel);
if (CallSites.size() < SiteNo)
CallSites.resize(SiteNo);
CallSites[SiteNo - 1] = Site;
}
PreviousIsInvoke = true;
}
}
}
//.........这里部分代码省略.........
示例13: ParseFile
//.........这里部分代码省略.........
TextDiagnosticPrinter TDP(SrcMgr);
DiagnosticsEngine Diag(new DiagnosticIDs,&SrcMgr, &TDP, false);
// Chain in -verify checker, if requested.
if(RunVerifier)
Diag.setClient(new VerifyDiagnosticConsumer(Diag));
ASTContext Context(SrcMgr, Opts);
Sema SA(Context, Diag);
Parser P(SrcMgr, Opts, Diag, SA);
Diag.getClient()->BeginSourceFile(Opts, &P.getLexer());
P.ParseProgramUnits();
Diag.getClient()->EndSourceFile();
// Dump
if(PrintAST || DumpAST) {
auto Dumper = CreateASTDumper("");
Dumper->HandleTranslationUnit(Context);
delete Dumper;
}
// Emit
if(!SyntaxOnly && !Diag.hadErrors()) {
flang::TargetOptions TargetOptions;
TargetOptions.Triple = TargetTriple.empty()? llvm::sys::getDefaultTargetTriple() :
TargetTriple;
TargetOptions.CPU = llvm::sys::getHostCPUName();
auto CG = CreateLLVMCodeGen(Diag, Filename == ""? std::string("module") : Filename,
CodeGenOptions(), TargetOptions, llvm::getGlobalContext());
CG->Initialize(Context);
CG->HandleTranslationUnit(Context);
BackendAction BA = Backend_EmitObj;
if(EmitASM) BA = Backend_EmitAssembly;
if(EmitLLVM) BA = Backend_EmitLL;
const llvm::Target *TheTarget = 0;
std::string Err;
TheTarget = llvm::TargetRegistry::lookupTarget(TargetOptions.Triple, Err);
CodeGenOpt::Level TMOptLevel = CodeGenOpt::Default;
switch(OptLevel) {
case 0: TMOptLevel = CodeGenOpt::None; break;
case 3: TMOptLevel = CodeGenOpt::Aggressive; break;
}
llvm::TargetOptions Options;
auto TM = TheTarget->createTargetMachine(TargetOptions.Triple, TargetOptions.CPU, "", Options,
Reloc::Default, CodeModel::Default,
TMOptLevel);
if(!(EmitLLVM && OptLevel == 0)) {
auto TheModule = CG->GetModule();
auto PM = new llvm::legacy::PassManager();
//llvm::legacy::FunctionPassManager *FPM = new llvm::legacy::FunctionPassManager(TheModule);
//FPM->add(new DataLayoutPass());
//PM->add(new llvm::DataLayoutPass());
//TM->addAnalysisPasses(*PM);
PM->add(createPromoteMemoryToRegisterPass());
PassManagerBuilder PMBuilder;
PMBuilder.OptLevel = OptLevel;
PMBuilder.SizeLevel = 0;
PMBuilder.LoopVectorize = true;
PMBuilder.SLPVectorize = true;
unsigned Threshold = 225;
if (OptLevel > 2)
Threshold = 275;
PMBuilder.Inliner = createFunctionInliningPass(Threshold);
PMBuilder.populateModulePassManager(*PM);
//llvm::legacy::PassManager *MPM = new llvm::legacy::PassManager();
//PMBuilder.populateModulePassManager(*MPM);
PM->run(*TheModule);
//MPM->run(*TheModule);
delete PM;
//delete MPM;
}
if(Interpret) {
//const char *Env[] = { "", nullptr };
//Execute(CG->ReleaseModule(), Env);
} else if(OutputFile == "-"){
// FIXME: outputting to stdout is broken
//EmitFile(llvm::outs(), CG->GetModule(), TM, BA);
OutputFiles.push_back(GetOutputName("stdout",BA));
EmitOutputFile(OutputFiles.back(), CG->GetModule(), TM, BA);
}else {
OutputFiles.push_back(GetOutputName(Filename, BA));
EmitOutputFile(OutputFiles.back(), CG->GetModule(), TM, BA);
}
delete CG;
}
return Diag.hadErrors();
}
示例14: assert
void X86CmovConverterPass::convertCmovInstsToBranches(
SmallVectorImpl<MachineInstr *> &Group) const {
assert(!Group.empty() && "No CMOV instructions to convert");
++NumOfOptimizedCmovGroups;
// If the CMOV group is not packed, e.g., there are debug instructions between
// first CMOV and last CMOV, then pack the group and make the CMOV instruction
// consecutive by moving the debug instructions to after the last CMOV.
packCmovGroup(Group.front(), Group.back());
// To convert a CMOVcc instruction, we actually have to insert the diamond
// control-flow pattern. The incoming instruction knows the destination vreg
// to set, the condition code register to branch on, the true/false values to
// select between, and a branch opcode to use.
// Before
// -----
// MBB:
// cond = cmp ...
// v1 = CMOVge t1, f1, cond
// v2 = CMOVlt t2, f2, cond
// v3 = CMOVge v1, f3, cond
//
// After
// -----
// MBB:
// cond = cmp ...
// jge %SinkMBB
//
// FalseMBB:
// jmp %SinkMBB
//
// SinkMBB:
// %v1 = phi[%f1, %FalseMBB], [%t1, %MBB]
// %v2 = phi[%t2, %FalseMBB], [%f2, %MBB] ; For CMOV with OppCC switch
// ; true-value with false-value
// %v3 = phi[%f3, %FalseMBB], [%t1, %MBB] ; Phi instruction cannot use
// ; previous Phi instruction result
MachineInstr &MI = *Group.front();
MachineInstr *LastCMOV = Group.back();
DebugLoc DL = MI.getDebugLoc();
X86::CondCode CC = X86::CondCode(X86::getCondFromCMovOpc(MI.getOpcode()));
X86::CondCode OppCC = X86::GetOppositeBranchCondition(CC);
// Potentially swap the condition codes so that any memory operand to a CMOV
// is in the *false* position instead of the *true* position. We can invert
// any non-memory operand CMOV instructions to cope with this and we ensure
// memory operand CMOVs are only included with a single condition code.
if (llvm::any_of(Group, [&](MachineInstr *I) {
return I->mayLoad() && X86::getCondFromCMovOpc(I->getOpcode()) == CC;
}))
std::swap(CC, OppCC);
MachineBasicBlock *MBB = MI.getParent();
MachineFunction::iterator It = ++MBB->getIterator();
MachineFunction *F = MBB->getParent();
const BasicBlock *BB = MBB->getBasicBlock();
MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(BB);
MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB);
F->insert(It, FalseMBB);
F->insert(It, SinkMBB);
// If the EFLAGS register isn't dead in the terminator, then claim that it's
// live into the sink and copy blocks.
if (checkEFLAGSLive(LastCMOV)) {
FalseMBB->addLiveIn(X86::EFLAGS);
SinkMBB->addLiveIn(X86::EFLAGS);
}
// Transfer the remainder of BB and its successor edges to SinkMBB.
SinkMBB->splice(SinkMBB->begin(), MBB,
std::next(MachineBasicBlock::iterator(LastCMOV)), MBB->end());
SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
// Add the false and sink blocks as its successors.
MBB->addSuccessor(FalseMBB);
MBB->addSuccessor(SinkMBB);
// Create the conditional branch instruction.
BuildMI(MBB, DL, TII->get(X86::GetCondBranchFromCond(CC))).addMBB(SinkMBB);
// Add the sink block to the false block successors.
FalseMBB->addSuccessor(SinkMBB);
MachineInstrBuilder MIB;
MachineBasicBlock::iterator MIItBegin = MachineBasicBlock::iterator(MI);
MachineBasicBlock::iterator MIItEnd =
std::next(MachineBasicBlock::iterator(LastCMOV));
MachineBasicBlock::iterator FalseInsertionPoint = FalseMBB->begin();
MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin();
// First we need to insert an explicit load on the false path for any memory
// operand. We also need to potentially do register rewriting here, but it is
// simpler as the memory operands are always on the false path so we can
// simply take that input, whatever it is.
DenseMap<unsigned, unsigned> FalseBBRegRewriteTable;
for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd;) {
auto &MI = *MIIt++;
//.........这里部分代码省略.........
示例15: parseFunctionArguments
/// Parse a function definition signature.
/// func-signature:
/// func-arguments func-throws? func-signature-result?
/// func-signature-result:
/// '->' type
///
/// Note that this leaves retType as null if unspecified.
ParserStatus
Parser::parseFunctionSignature(Identifier SimpleName,
DeclName &FullName,
SmallVectorImpl<ParameterList*> &bodyParams,
DefaultArgumentInfo &defaultArgs,
SourceLoc &throwsLoc,
bool &rethrows,
TypeRepr *&retType) {
SmallVector<Identifier, 4> NamePieces;
NamePieces.push_back(SimpleName);
FullName = SimpleName;
ParserStatus Status;
// We force first type of a func declaration to be a tuple for consistency.
if (Tok.is(tok::l_paren)) {
ParameterContextKind paramContext;
if (SimpleName.isOperator())
paramContext = ParameterContextKind::Operator;
else
paramContext = ParameterContextKind::Function;
Status = parseFunctionArguments(NamePieces, bodyParams, paramContext,
defaultArgs);
FullName = DeclName(Context, SimpleName,
llvm::makeArrayRef(NamePieces.begin() + 1,
NamePieces.end()));
if (bodyParams.empty()) {
// If we didn't get anything, add a () pattern to avoid breaking
// invariants.
assert(Status.hasCodeCompletion() || Status.isError());
bodyParams.push_back(ParameterList::createEmpty(Context));
}
} else {
diagnose(Tok, diag::func_decl_without_paren);
Status = makeParserError();
// Recover by creating a '() -> ?' signature.
bodyParams.push_back(ParameterList::createEmpty(Context, PreviousLoc,
PreviousLoc));
FullName = DeclName(Context, SimpleName, bodyParams.back());
}
// Check for the 'throws' keyword.
rethrows = false;
if (Tok.is(tok::kw_throws)) {
throwsLoc = consumeToken();
} else if (Tok.is(tok::kw_rethrows)) {
throwsLoc = consumeToken();
rethrows = true;
} else if (Tok.is(tok::kw_throw)) {
throwsLoc = consumeToken();
diagnose(throwsLoc, diag::throw_in_function_type)
.fixItReplace(throwsLoc, "throws");
}
SourceLoc arrowLoc;
// If there's a trailing arrow, parse the rest as the result type.
if (Tok.isAny(tok::arrow, tok::colon)) {
if (!consumeIf(tok::arrow, arrowLoc)) {
// FixIt ':' to '->'.
diagnose(Tok, diag::func_decl_expected_arrow)
.fixItReplace(SourceRange(Tok.getLoc()), "->");
arrowLoc = consumeToken(tok::colon);
}
ParserResult<TypeRepr> ResultType =
parseType(diag::expected_type_function_result);
if (ResultType.hasCodeCompletion())
return ResultType;
retType = ResultType.getPtrOrNull();
if (!retType) {
Status.setIsParseError();
return Status;
}
} else {
// Otherwise, we leave retType null.
retType = nullptr;
}
// Check for 'throws' and 'rethrows' after the type and correct it.
if (!throwsLoc.isValid()) {
if (Tok.is(tok::kw_throws)) {
throwsLoc = consumeToken();
} else if (Tok.is(tok::kw_rethrows)) {
throwsLoc = consumeToken();
rethrows = true;
}
if (throwsLoc.isValid()) {
assert(arrowLoc.isValid());
assert(retType);
auto diag = rethrows ? diag::rethrows_after_function_result
//.........这里部分代码省略.........