Files
freebsd/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
T
Dimitry Andric e8948c9522 Merge clang, llvm, lld, lldb, compiler-rt and libc++ 5.0.0 release.
MFC r309126 (by emaste):

  Correct lld llvm-tblgen dependency file name

MFC r309169:

  Get rid of separate Subversion mergeinfo properties for llvm-dwarfdump
  and llvm-lto.  The mergeinfo confuses Subversion enormously, and these
  directories will just use the mergeinfo for llvm itself.

MFC r312765:

  Pull in r276136 from upstream llvm trunk (by Wei Mi):

    Use ValueOffsetPair to enhance value reuse during SCEV expansion.

    In D12090, the ExprValueMap was added to reuse existing value during
    SCEV expansion. However, const folding and sext/zext distribution can
    make the reuse still difficult.

    A simplified case is: suppose we know S1 expands to V1 in
    ExprValueMap, and
      S1 = S2 + C_a
      S3 = S2 + C_b
    where C_a and C_b are different SCEVConstants. Then we'd like to
    expand S3 as V1 - C_a + C_b instead of expanding S2 literally. It is
    helpful when S2 is a complex SCEV expr and S2 has no entry in
    ExprValueMap, which is usually caused by the fact that S3 is
    generated from S1 after const folding.

    In order to do that, we represent ExprValueMap as a mapping from SCEV
    to ValueOffsetPair. We will save both S1->{V1, 0} and S2->{V1, C_a}
    into the ExprValueMap when we create SCEV for V1. When S3 is
    expanded, it will first expand S2 to V1 - C_a because of S2->{V1,
    C_a} in the map, then expand S3 to V1 - C_a + C_b.

    Differential Revision: https://reviews.llvm.org/D21313

  This should fix assertion failures when building OpenCV >= 3.1.

  PR:		215649

MFC r312831:

  Revert r312765 for now, since it causes assertions when building
  lang/spidermonkey24.

  Reported by:	antoine
  PR:		215649

MFC r316511 (by jhb):

  Add an implementation of __ffssi2() derived from __ffsdi2().

  Newer versions of GCC include an __ffssi2() symbol in libgcc and the
  compiler can emit calls to it in generated code.  This is true for at
  least GCC 6.2 when compiling world for mips and mips64.

  Reviewed by:	jmallett, dim
  Sponsored by:	DARPA / AFRL
  Differential Revision:	https://reviews.freebsd.org/D10086

MFC r318601 (by adrian):

  [libcompiler-rt] add bswapdi2/bswapsi2

  This is required for mips gcc 6.3 userland to build/run.

  Reviewed by:	emaste, dim
  Approved by:	emaste
  Differential Revision:	https://reviews.freebsd.org/D10838

MFC r318884 (by emaste):

  lldb: map TRAP_CAP to a trace trap

  In the absense of a more specific handler for TRAP_CAP (generated by
  ENOTCAPABLE or ECAPMODE while in capability mode) treat it as a trace
  trap.

  Example usage (testing the bug in PR219173):

  % proccontrol -m trapcap lldb usr.bin/hexdump/obj/hexdump -- -Cv -s 1 /bin/ls
  ...
  (lldb) run
  Process 12980 launching
  Process 12980 launched: '.../usr.bin/hexdump/obj/hexdump' (x86_64)
  Process 12980 stopped
  * thread #1, stop reason = trace
      frame #0: 0x0000004b80c65f1a libc.so.7`__sys_lseek + 10
  ...

  In the future we should have LLDB control the trapcap procctl itself
  (as it does with ASLR), as well as report a specific stop reason.
  This change eliminates an assertion failure from LLDB for now.

MFC r319796:

  Remove a few unneeded files from libllvm, libclang and liblldb.

MFC r319885 (by emaste):

  lld: ELF: Fix ICF crash on absolute symbol relocations.

  If two sections contained relocations to absolute symbols with the same
  value we would crash when trying to access their sections. Add a check that
  both symbols point to sections before accessing their sections, and treat
  absolute symbols as equal if their values are equal.

  Obtained from:	LLD commit r292578

MFC r319918:

  Revert r319796 for now, it can cause undefined references when linking
  in some circumstances.

  Reported by:	Shawn Webb <[email protected]>

MFC r319957 (by emaste):

  lld: Add armelf emulation mode

  Obtained from:	LLD r305375

MFC r321369:

  Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
  5.0.0 (trunk r308421).  Upstream has branched for the 5.0.0 release,
  which should be in about a month.  Please report bugs and regressions,
  so we can get them into the release.

  Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
  support to build; see UPDATING for more information.

MFC r321420:

  Add a few more object files to liblldb, which should solve errors when
  linking the lldb executable in some cases.  In particular, when the
  -ffunction-sections -fdata-sections options are turned off, or
  ineffective.

  Reported by:	Shawn Webb, Mark Millard

MFC r321433:

  Cleanup stale Options.inc files from the previous libllvm build for
  clang 4.0.0.  Otherwise, these can get included before the two newly
  generated ones (which are different) for clang 5.0.0.

  Reported by:	Mark Millard

MFC r321439 (by bdrewery):

  Move llvm Options.inc hack from r321433 for NO_CLEAN to lib/clang/libllvm.

  The files are only ever generated to .OBJDIR, not to WORLDTMP (as a
  sysroot) and are only ever included from a compilation.  So using
  a beforebuild target here removes the file before the compilation
  tries to include it.

MFC r321664:

  Pull in r308891 from upstream llvm trunk (by Benjamin Kramer):

    [CodeGenPrepare] Cut off FindAllMemoryUses if there are too many uses.

    This avoids excessive compile time. The case I'm looking at is
    Function.cpp from an old version of LLVM that still had the giant
    memcmp string matcher in it. Before r308322 this compiled in about 2
    minutes, after it, clang takes infinite* time to compile it. With
    this patch we're at 5 min, which is still bad but this is a
    pathological case.

    The cut off at 20 uses was chosen by looking at other cut-offs in LLVM
    for user scanning. It's probably too high, but does the job and is
    very unlikely to regress anything.

    Fixes PR33900.

    * I'm impatient and aborted after 15 minutes, on the bug report it was
      killed after 2h.

  Pull in r308986 from upstream llvm trunk (by Simon Pilgrim):

    [X86][CGP] Reduce memcmp() expansion to 2 load pairs (PR33914)

    D35067/rL308322 attempted to support up to 4 load pairs for memcmp
    inlining which resulted in regressions for some optimized libc memcmp
    implementations (PR33914).

    Until we can match these more optimal cases, this patch reduces the
    memcmp expansion to a maximum of 2 load pairs (which matches what we
    do for -Os).

    This patch should be considered for the 5.0.0 release branch as well

    Differential Revision: https://reviews.llvm.org/D35830

  These fix a hang (or extremely long compile time) when building older
  LLVM ports.

  Reported by:    antoine
  PR:             219139

MFC r321719:

  Pull in r309503 from upstream clang trunk (by Richard Smith):

    PR33902: Invalidate line number cache when adding more text to
    existing buffer.

    This led to crashes as the line number cache would report a bogus
    line number for a line of code, and we'd try to find a nonexistent
    column within the line when printing diagnostics.

  This fixes an assertion when building the graphics/champlain port.

  Reported by:	antoine, kwm
  PR:		219139

MFC r321723:

  Upgrade our copies of clang, llvm, lld and lldb to r309439 from the
  upstream release_50 branch.  This is just after upstream's 5.0.0-rc1.

MFC r322320:

  Upgrade our copies of clang, llvm and libc++ to r310316 from the
  upstream release_50 branch.

MFC r322326 (by emaste):

  lldb: Make i386-*-freebsd expression work on JIT path

  * Enable i386 ABI creation for freebsd
  * Added an extra argument in ABISysV_i386::PrepareTrivialCall for mmap
    syscall
  * Unlike linux, the last argument of mmap is actually 64-bit(off_t).
    This requires us to push an additional word for the higher order bits.
  * Prior to this change, ktrace dump will show mmap failures due to
    invalid argument coming from the 6th mmap argument.

  Submitted by:	Karnajit Wangkhem
  Differential Revision:	https://reviews.llvm.org/D34776

MFC r322360 (by emaste):

  lldb: Report inferior signals as signals, not exceptions, on FreeBSD

  This is the FreeBSD equivalent of LLVM r238549.

  This serves 2 purposes:

  * LLDB should handle inferior process signals SIGSEGV/SIGILL/SIGBUS/
    SIGFPE the way it is suppose to be handled. Prior to this fix these
    signals will neither create a coredump, nor exit from the debugger
    or work for signal handling scenario.
  * eInvalidCrashReason need not report "unknown crash reason" if we have
    a valid si_signo

  llvm.org/pr23699

  Patch by Karnajit Wangkhem

  Differential Revision:  https://reviews.llvm.org/D35223

  Submitted by:	Karnajit Wangkhem
  Obtained from:	LLVM r310591

MFC r322474 (by emaste):

  lld: Add `-z muldefs` option.

  Obtained from:	LLVM r310757

MFC r322740:

  Upgrade our copies of clang, llvm, lld and libc++ to r311219 from the
  upstream release_50 branch.

MFC r322855:

  Upgrade our copies of clang, llvm, lldb and compiler-rt to r311606 from
  the upstream release_50 branch.

  As of this version, lib/msun's trig test should also work correctly
  again (see bug 220989 for more information).

  PR:		220989

MFC r323112:

  Upgrade our copies of clang, llvm, lldb and compiler-rt to r312293 from
  the upstream release_50 branch.  This corresponds to 5.0.0 rc4.

  As of this version, the cad/stepcode port should now compile in a more
  reasonable time on i386 (see bug 221836 for more information).

  PR:		221836

MFC r323245:

  Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
  5.0.0 release (upstream r312559).

  Release notes for llvm, clang and lld will be available here soon:
  <http://releases.llvm.org/5.0.0/docs/ReleaseNotes.html>
  <http://releases.llvm.org/5.0.0/tools/clang/docs/ReleaseNotes.html>
  <http://releases.llvm.org/5.0.0/tools/lld/docs/ReleaseNotes.html>

  Relnotes:	yes
2017-09-26 19:56:36 +00:00

471 lines
17 KiB
C++

//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the DAG Matcher optimizer.
//
//===----------------------------------------------------------------------===//
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "isel-opt"
/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
/// into single compound nodes like RecordChild.
static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
const CodeGenDAGPatterns &CGP) {
// If we reached the end of the chain, we're done.
Matcher *N = MatcherPtr.get();
if (!N) return;
// If we have a scope node, walk down all of the children.
if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
std::unique_ptr<Matcher> Child(Scope->takeChild(i));
ContractNodes(Child, CGP);
Scope->resetChild(i, Child.release());
}
return;
}
// If we found a movechild node with a node that comes in a 'foochild' form,
// transform it.
if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
Matcher *New = nullptr;
if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
if (MC->getChildNo() < 8) // Only have RecordChild0...7
New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
RM->getResultNo());
if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
CT->getResNo() == 0) // CheckChildType checks res #0
New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext()))
if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue());
if (New) {
// Insert the new node.
New->setNext(MatcherPtr.release());
MatcherPtr.reset(New);
// Remove the old one.
MC->setNext(MC->getNext()->takeNext());
return ContractNodes(MatcherPtr, CGP);
}
}
// Zap movechild -> moveparent.
if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
if (MoveParentMatcher *MP =
dyn_cast<MoveParentMatcher>(MC->getNext())) {
MatcherPtr.reset(MP->takeNext());
return ContractNodes(MatcherPtr, CGP);
}
// Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
if (CompleteMatchMatcher *CM =
dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
// We can only use MorphNodeTo if the result values match up.
unsigned RootResultFirst = EN->getFirstResultSlot();
bool ResultsMatch = true;
for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
if (CM->getResult(i) != RootResultFirst+i)
ResultsMatch = false;
// If the selected node defines a subset of the glue/chain results, we
// can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
// matched pattern has a chain but the root node doesn't.
const PatternToMatch &Pattern = CM->getPattern();
if (!EN->hasChain() &&
Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
ResultsMatch = false;
// If the matched node has glue and the output root doesn't, we can't
// use MorphNodeTo.
//
// NOTE: Strictly speaking, we don't have to check for glue here
// because the code in the pattern generator doesn't handle it right. We
// do it anyway for thoroughness.
if (!EN->hasOutFlag() &&
Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP))
ResultsMatch = false;
// If the root result node defines more results than the source root node
// *and* has a chain or glue input, then we can't match it because it
// would end up replacing the extra result with the chain/glue.
#if 0
if ((EN->hasGlue() || EN->hasChain()) &&
EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...)
ResultMatch = false;
#endif
if (ResultsMatch) {
const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(),
VTs, Operands,
EN->hasChain(), EN->hasInFlag(),
EN->hasOutFlag(),
EN->hasMemRefs(),
EN->getNumFixedArityOperands(),
Pattern));
return;
}
// FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
// variants.
}
ContractNodes(N->getNextPtr(), CGP);
// If we have a CheckType/CheckChildType/Record node followed by a
// CheckOpcode, invert the two nodes. We prefer to do structural checks
// before type checks, as this opens opportunities for factoring on targets
// like X86 where many operations are valid on multiple types.
if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||
isa<RecordMatcher>(N)) &&
isa<CheckOpcodeMatcher>(N->getNext())) {
// Unlink the two nodes from the list.
Matcher *CheckType = MatcherPtr.release();
Matcher *CheckOpcode = CheckType->takeNext();
Matcher *Tail = CheckOpcode->takeNext();
// Relink them.
MatcherPtr.reset(CheckOpcode);
CheckOpcode->setNext(CheckType);
CheckType->setNext(Tail);
return ContractNodes(MatcherPtr, CGP);
}
}
/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
/// specified kind. Return null if we didn't find one otherwise return the
/// matcher.
static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
for (; M; M = M->getNext())
if (M->getKind() == Kind)
return M;
return nullptr;
}
/// FactorNodes - Turn matches like this:
/// Scope
/// OPC_CheckType i32
/// ABC
/// OPC_CheckType i32
/// XYZ
/// into:
/// OPC_CheckType i32
/// Scope
/// ABC
/// XYZ
///
static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
// Look for a push node. Iterates instead of recurses to reduce stack usage.
ScopeMatcher *Scope = nullptr;
std::unique_ptr<Matcher> *RebindableMatcherPtr = &InputMatcherPtr;
while (!Scope) {
// If we reached the end of the chain, we're done.
Matcher *N = RebindableMatcherPtr->get();
if (!N) return;
// If this is not a push node, just scan for one.
Scope = dyn_cast<ScopeMatcher>(N);
if (!Scope)
RebindableMatcherPtr = &(N->getNextPtr());
}
std::unique_ptr<Matcher> &MatcherPtr = *RebindableMatcherPtr;
// Okay, pull together the children of the scope node into a vector so we can
// inspect it more easily.
SmallVector<Matcher*, 32> OptionsToMatch;
for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
// Factor the subexpression.
std::unique_ptr<Matcher> Child(Scope->takeChild(i));
FactorNodes(Child);
if (Child) {
// If the child is a ScopeMatcher we can just merge its contents.
if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {
for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j)
OptionsToMatch.push_back(SM->takeChild(j));
} else {
OptionsToMatch.push_back(Child.release());
}
}
}
SmallVector<Matcher*, 32> NewOptionsToMatch;
// Loop over options to match, merging neighboring patterns with identical
// starting nodes into a shared matcher.
for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {
// Find the set of matchers that start with this node.
Matcher *Optn = OptionsToMatch[OptionIdx++];
if (OptionIdx == e) {
NewOptionsToMatch.push_back(Optn);
continue;
}
// See if the next option starts with the same matcher. If the two
// neighbors *do* start with the same matcher, we can factor the matcher out
// of at least these two patterns. See what the maximal set we can merge
// together is.
SmallVector<Matcher*, 8> EqualMatchers;
EqualMatchers.push_back(Optn);
// Factor all of the known-equal matchers after this one into the same
// group.
while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))
EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);
// If we found a non-equal matcher, see if it is contradictory with the
// current node. If so, we know that the ordering relation between the
// current sets of nodes and this node don't matter. Look past it to see if
// we can merge anything else into this matching group.
unsigned Scan = OptionIdx;
while (1) {
// If we ran out of stuff to scan, we're done.
if (Scan == e) break;
Matcher *ScanMatcher = OptionsToMatch[Scan];
// If we found an entry that matches out matcher, merge it into the set to
// handle.
if (Optn->isEqual(ScanMatcher)) {
// If is equal after all, add the option to EqualMatchers and remove it
// from OptionsToMatch.
EqualMatchers.push_back(ScanMatcher);
OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
--e;
continue;
}
// If the option we're checking for contradicts the start of the list,
// skip over it.
if (Optn->isContradictory(ScanMatcher)) {
++Scan;
continue;
}
// If we're scanning for a simple node, see if it occurs later in the
// sequence. If so, and if we can move it up, it might be contradictory
// or the same as what we're looking for. If so, reorder it.
if (Optn->isSimplePredicateOrRecordNode()) {
Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
if (M2 && M2 != ScanMatcher &&
M2->canMoveBefore(ScanMatcher) &&
(M2->isEqual(Optn) || M2->isContradictory(Optn))) {
Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
M2->setNext(MatcherWithoutM2);
OptionsToMatch[Scan] = M2;
continue;
}
}
// Otherwise, we don't know how to handle this entry, we have to bail.
break;
}
if (Scan != e &&
// Don't print it's obvious nothing extra could be merged anyway.
Scan+1 != e) {
DEBUG(errs() << "Couldn't merge this:\n";
Optn->print(errs(), 4);
errs() << "into this:\n";
OptionsToMatch[Scan]->print(errs(), 4);
if (Scan+1 != e)
OptionsToMatch[Scan+1]->printOne(errs());
if (Scan+2 < e)
OptionsToMatch[Scan+2]->printOne(errs());
errs() << "\n");
}
// If we only found one option starting with this matcher, no factoring is
// possible.
if (EqualMatchers.size() == 1) {
NewOptionsToMatch.push_back(EqualMatchers[0]);
continue;
}
// Factor these checks by pulling the first node off each entry and
// discarding it. Take the first one off the first entry to reuse.
Matcher *Shared = Optn;
Optn = Optn->takeNext();
EqualMatchers[0] = Optn;
// Remove and delete the first node from the other matchers we're factoring.
for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
Matcher *Tmp = EqualMatchers[i]->takeNext();
delete EqualMatchers[i];
EqualMatchers[i] = Tmp;
}
Shared->setNext(new ScopeMatcher(EqualMatchers));
// Recursively factor the newly created node.
FactorNodes(Shared->getNextPtr());
NewOptionsToMatch.push_back(Shared);
}
// If we're down to a single pattern to match, then we don't need this scope
// anymore.
if (NewOptionsToMatch.size() == 1) {
MatcherPtr.reset(NewOptionsToMatch[0]);
return;
}
if (NewOptionsToMatch.empty()) {
MatcherPtr.reset();
return;
}
// If our factoring failed (didn't achieve anything) see if we can simplify in
// other ways.
// Check to see if all of the leading entries are now opcode checks. If so,
// we can convert this Scope to be a OpcodeSwitch instead.
bool AllOpcodeChecks = true, AllTypeChecks = true;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
// Check to see if this breaks a series of CheckOpcodeMatchers.
if (AllOpcodeChecks &&
!isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
#if 0
if (i > 3) {
errs() << "FAILING OPC #" << i << "\n";
NewOptionsToMatch[i]->dump();
}
#endif
AllOpcodeChecks = false;
}
// Check to see if this breaks a series of CheckTypeMatcher's.
if (AllTypeChecks) {
CheckTypeMatcher *CTM =
cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
Matcher::CheckType));
if (!CTM ||
// iPTR checks could alias any other case without us knowing, don't
// bother with them.
CTM->getType() == MVT::iPTR ||
// SwitchType only works for result #0.
CTM->getResNo() != 0 ||
// If the CheckType isn't at the start of the list, see if we can move
// it there.
!CTM->canMoveBefore(NewOptionsToMatch[i])) {
#if 0
if (i > 3 && AllTypeChecks) {
errs() << "FAILING TYPE #" << i << "\n";
NewOptionsToMatch[i]->dump();
}
#endif
AllTypeChecks = false;
}
}
}
// If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
if (AllOpcodeChecks) {
StringSet<> Opcodes;
SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
"Duplicate opcodes not factored?");
Cases.push_back(std::make_pair(&COM->getOpcode(), COM->takeNext()));
delete COM;
}
MatcherPtr.reset(new SwitchOpcodeMatcher(Cases));
return;
}
// If all the options are CheckType's, we can form the SwitchType, woot.
if (AllTypeChecks) {
DenseMap<unsigned, unsigned> TypeEntry;
SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
CheckTypeMatcher *CTM =
cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
Matcher::CheckType));
Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
MVT::SimpleValueType CTMTy = CTM->getType();
delete CTM;
unsigned &Entry = TypeEntry[CTMTy];
if (Entry != 0) {
// If we have unfactored duplicate types, then we should factor them.
Matcher *PrevMatcher = Cases[Entry-1].second;
if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
SM->setNumChildren(SM->getNumChildren()+1);
SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);
continue;
}
Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
Cases[Entry-1].second = new ScopeMatcher(Entries);
continue;
}
Entry = Cases.size()+1;
Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
}
// Make sure we recursively factor any scopes we may have created.
for (auto &M : Cases) {
if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {
std::unique_ptr<Matcher> Scope(SM);
FactorNodes(Scope);
M.second = Scope.release();
assert(M.second && "null matcher");
}
}
if (Cases.size() != 1) {
MatcherPtr.reset(new SwitchTypeMatcher(Cases));
} else {
// If we factored and ended up with one case, create it now.
MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
MatcherPtr->setNext(Cases[0].second);
}
return;
}
// Reassemble the Scope node with the adjusted children.
Scope->setNumChildren(NewOptionsToMatch.size());
for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)
Scope->resetChild(i, NewOptionsToMatch[i]);
}
void
llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
const CodeGenDAGPatterns &CGP) {
ContractNodes(MatcherPtr, CGP);
FactorNodes(MatcherPtr);
}