Mark files not in r294123 as dead.

This commit is contained in:
joerg 2017-02-09 17:54:06 +00:00
parent c411cea556
commit 1bf9ae99e4
37 changed files with 0 additions and 4326 deletions

View File

@ -1,149 +0,0 @@
//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This header provides classes for managing passes over loops in LLVM IR.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H
#define LLVM_ANALYSIS_LOOPPASSMANAGER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
extern template class PassManager<Loop>;
/// \brief The loop pass manager.
///
/// See the documentation for the PassManager template for details. It runs a
/// sequency of loop passes over each loop that the manager is run over. This
/// typedef serves as a convenient way to refer to this construct.
typedef PassManager<Loop> LoopPassManager;
extern template class AnalysisManager<Loop>;
/// \brief The loop analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
/// documentation. This typedef serves as a convenient way to refer to this
/// construct in the adaptors and proxies used to integrate this into the larger
/// pass manager infrastructure.
typedef AnalysisManager<Loop> LoopAnalysisManager;
/// A proxy from a \c LoopAnalysisManager to a \c Function.
typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
LoopAnalysisManagerFunctionProxy;
/// Specialization of the invalidate method for the \c
/// LoopAnalysisManagerFunctionProxy's result.
template <>
bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
// Ensure the \c LoopAnalysisManagerFunctionProxy is provided as an extern
// template.
extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
/// A proxy from a \c FunctionAnalysisManager to a \c Loop.
typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
FunctionAnalysisManagerLoopProxy;
/// Returns the minimum set of Analyses that all loop passes must preserve.
PreservedAnalyses getLoopPassPreservedAnalyses();
/// \brief Adaptor that maps from a function to its loops.
///
/// Designed to allow composition of a LoopPass(Manager) and a
/// FunctionPassManager. Note that if this pass is constructed with a \c
/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
/// analysis prior to running the loop passes over the function to enable a \c
/// LoopAnalysisManager to be used within this run safely.
template <typename LoopPassT>
class FunctionToLoopPassAdaptor
: public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
public:
explicit FunctionToLoopPassAdaptor(LoopPassT Pass)
: Pass(std::move(Pass)) {}
/// \brief Runs the loop passes across every loop in the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
// Setup the loop analysis manager from its proxy.
LoopAnalysisManager &LAM =
AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
// Get the loop structure for this function
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
// Also precompute all of the function analyses used by loop passes.
// FIXME: These should be handed into the loop passes when the loop pass
// management layer is reworked to follow the design of CGSCC.
(void)AM.getResult<AAManager>(F);
(void)AM.getResult<DominatorTreeAnalysis>(F);
(void)AM.getResult<ScalarEvolutionAnalysis>(F);
(void)AM.getResult<TargetLibraryAnalysis>(F);
PreservedAnalyses PA = PreservedAnalyses::all();
// We want to visit the loops in reverse post-order. We'll build the stack
// of loops to visit in Loops by first walking the loops in pre-order.
SmallVector<Loop *, 2> Loops;
SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end());
while (!WorkList.empty()) {
Loop *L = WorkList.pop_back_val();
WorkList.insert(WorkList.end(), L->begin(), L->end());
Loops.push_back(L);
}
// Now pop each element off of the stack to visit the loops in reverse
// post-order.
for (auto *L : reverse(Loops)) {
PreservedAnalyses PassPA = Pass.run(*L, LAM);
// FIXME: We should verify the set of analyses relevant to Loop passes
// are preserved.
// We know that the loop pass couldn't have invalidated any other loop's
// analyses (that's the contract of a loop pass), so directly handle the
// loop analysis manager's invalidation here.
LAM.invalidate(*L, PassPA);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
PA.intersect(std::move(PassPA));
}
// By definition we preserve the proxy. We also preserve all analyses on
// Loops. This precludes *any* invalidation of loop analyses by the proxy,
// but that's OK because we've taken care to invalidate analyses in the
// loop analysis manager incrementally above.
PA.preserveSet<AllAnalysesOn<Loop>>();
PA.preserve<LoopAnalysisManagerFunctionProxy>();
return PA;
}
private:
LoopPassT Pass;
};
/// \brief A function to deduce a loop pass type and wrap it in the templated
/// adaptor.
template <typename LoopPassT>
FunctionToLoopPassAdaptor<LoopPassT>
createFunctionToLoopPassAdaptor(LoopPassT Pass) {
return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass));
}
}
#endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H

View File

@ -1,108 +0,0 @@
//===-- TypeDumper.h - CodeView type info dumper ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
namespace llvm {
class ScopedPrinter;
namespace codeview {
/// Dumper for CodeView type streams found in COFF object files and PDB files.
class CVTypeDumper : public TypeVisitorCallbacks {
public:
CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes)
: W(W), PrintRecordBytes(PrintRecordBytes) {}
StringRef getTypeName(TypeIndex TI);
void printTypeIndex(StringRef FieldName, TypeIndex TI);
/// Dumps one type record. Returns false if there was a type parsing error,
/// and true otherwise. This should be called in order, since the dumper
/// maintains state about previous records which are necessary for cross
/// type references.
Error dump(const CVRecord<TypeLeafKind> &Record);
/// Dumps the type records in Types. Returns false if there was a type stream
/// parse error, and true otherwise.
Error dump(const CVTypeArray &Types);
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise. Use this method instead of the
/// CVTypeArray overload when type records are laid out contiguously in
/// memory.
Error dump(ArrayRef<uint8_t> Data);
/// Gets the type index for the next type record.
unsigned getNextTypeIndex() const {
return 0x1000 + CVUDTNames.size();
}
/// Records the name of a type, and reserves its type index.
void recordType(StringRef Name) { CVUDTNames.push_back(Name); }
/// Saves the name in a StringSet and creates a stable StringRef.
StringRef saveName(StringRef TypeName) {
return TypeNames.insert(TypeName).first->getKey();
}
void setPrinter(ScopedPrinter *P);
ScopedPrinter *getPrinter() { return W; }
/// Action to take on unknown types. By default, they are ignored.
Error visitUnknownType(CVType &Record) override;
Error visitUnknownMember(CVMemberRecord &Record) override;
/// Paired begin/end actions for all types. Receives all record data,
/// including the fixed-length record prefix.
Error visitTypeBegin(CVType &Record) override;
Error visitTypeEnd(CVType &Record) override;
Error visitMemberBegin(CVMemberRecord &Record) override;
Error visitMemberEnd(CVMemberRecord &Record) override;
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"
private:
void printMemberAttributes(MemberAttributes Attrs);
void printMemberAttributes(MemberAccess Access, MethodKind Kind,
MethodOptions Options);
ScopedPrinter *W;
bool IsInFieldList = false;
bool PrintRecordBytes = false;
/// Name of the current type. Only valid before visitTypeEnd.
StringRef Name;
/// All user defined type records in .debug$T live in here. Type indices
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
/// index into this vector.
SmallVector<StringRef, 10> CVUDTNames;
StringSet<> TypeNames;
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H

View File

@ -1,59 +0,0 @@
//===- LoopPassManager.cpp - Loop pass management -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/IR/Dominators.h"
using namespace llvm;
// Explicit template instantiations and specialization defininitions for core
// template typedefs.
namespace llvm {
template class PassManager<Loop>;
template class AnalysisManager<Loop>;
template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
template <>
bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv) {
// If this proxy isn't marked as preserved, the set of Function objects in
// the module may have changed. We therefore can't call
// InnerAM->invalidate(), because any pointers to Functions it has may be
// stale.
auto PAC = PA.getChecker<LoopAnalysisManagerFunctionProxy>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Loop>>())
InnerAM->clear();
// FIXME: Proper suppor for invalidation isn't yet implemented for the LPM.
// Return false to indicate that this result is still a valid proxy.
return false;
}
}
PreservedAnalyses llvm::getLoopPassPreservedAnalyses() {
PreservedAnalyses PA;
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
PA.preserve<ScalarEvolutionAnalysis>();
// TODO: What we really want to do here is preserve an AA category, but that
// concept doesn't exist yet.
PA.preserve<AAManager>();
PA.preserve<BasicAA>();
PA.preserve<GlobalsAA>();
PA.preserve<SCEVAA>();
return PA;
}

View File

@ -1,772 +0,0 @@
//===-- TypeDumper.cpp - CodeView type info dumper --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
using namespace llvm::codeview;
/// The names here all end in "*". If the simple type is a pointer type, we
/// return the whole name. Otherwise we lop off the last character in our
/// StringRef.
static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
{"void*", SimpleTypeKind::Void},
{"<not translated>*", SimpleTypeKind::NotTranslated},
{"HRESULT*", SimpleTypeKind::HResult},
{"signed char*", SimpleTypeKind::SignedCharacter},
{"unsigned char*", SimpleTypeKind::UnsignedCharacter},
{"char*", SimpleTypeKind::NarrowCharacter},
{"wchar_t*", SimpleTypeKind::WideCharacter},
{"char16_t*", SimpleTypeKind::Character16},
{"char32_t*", SimpleTypeKind::Character32},
{"__int8*", SimpleTypeKind::SByte},
{"unsigned __int8*", SimpleTypeKind::Byte},
{"short*", SimpleTypeKind::Int16Short},
{"unsigned short*", SimpleTypeKind::UInt16Short},
{"__int16*", SimpleTypeKind::Int16},
{"unsigned __int16*", SimpleTypeKind::UInt16},
{"long*", SimpleTypeKind::Int32Long},
{"unsigned long*", SimpleTypeKind::UInt32Long},
{"int*", SimpleTypeKind::Int32},
{"unsigned*", SimpleTypeKind::UInt32},
{"__int64*", SimpleTypeKind::Int64Quad},
{"unsigned __int64*", SimpleTypeKind::UInt64Quad},
{"__int64*", SimpleTypeKind::Int64},
{"unsigned __int64*", SimpleTypeKind::UInt64},
{"__int128*", SimpleTypeKind::Int128},
{"unsigned __int128*", SimpleTypeKind::UInt128},
{"__half*", SimpleTypeKind::Float16},
{"float*", SimpleTypeKind::Float32},
{"float*", SimpleTypeKind::Float32PartialPrecision},
{"__float48*", SimpleTypeKind::Float48},
{"double*", SimpleTypeKind::Float64},
{"long double*", SimpleTypeKind::Float80},
{"__float128*", SimpleTypeKind::Float128},
{"_Complex float*", SimpleTypeKind::Complex32},
{"_Complex double*", SimpleTypeKind::Complex64},
{"_Complex long double*", SimpleTypeKind::Complex80},
{"_Complex __float128*", SimpleTypeKind::Complex128},
{"bool*", SimpleTypeKind::Boolean8},
{"__bool16*", SimpleTypeKind::Boolean16},
{"__bool32*", SimpleTypeKind::Boolean32},
{"__bool64*", SimpleTypeKind::Boolean64},
};
static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
};
#define ENUM_ENTRY(enum_class, enum) \
{ #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
static const EnumEntry<uint16_t> ClassOptionNames[] = {
ENUM_ENTRY(ClassOptions, Packed),
ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor),
ENUM_ENTRY(ClassOptions, HasOverloadedOperator),
ENUM_ENTRY(ClassOptions, Nested),
ENUM_ENTRY(ClassOptions, ContainsNestedClass),
ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator),
ENUM_ENTRY(ClassOptions, HasConversionOperator),
ENUM_ENTRY(ClassOptions, ForwardReference),
ENUM_ENTRY(ClassOptions, Scoped),
ENUM_ENTRY(ClassOptions, HasUniqueName),
ENUM_ENTRY(ClassOptions, Sealed),
ENUM_ENTRY(ClassOptions, Intrinsic),
};
static const EnumEntry<uint8_t> MemberAccessNames[] = {
ENUM_ENTRY(MemberAccess, None),
ENUM_ENTRY(MemberAccess, Private),
ENUM_ENTRY(MemberAccess, Protected),
ENUM_ENTRY(MemberAccess, Public),
};
static const EnumEntry<uint16_t> MethodOptionNames[] = {
ENUM_ENTRY(MethodOptions, Pseudo),
ENUM_ENTRY(MethodOptions, NoInherit),
ENUM_ENTRY(MethodOptions, NoConstruct),
ENUM_ENTRY(MethodOptions, CompilerGenerated),
ENUM_ENTRY(MethodOptions, Sealed),
};
static const EnumEntry<uint16_t> MemberKindNames[] = {
ENUM_ENTRY(MethodKind, Vanilla),
ENUM_ENTRY(MethodKind, Virtual),
ENUM_ENTRY(MethodKind, Static),
ENUM_ENTRY(MethodKind, Friend),
ENUM_ENTRY(MethodKind, IntroducingVirtual),
ENUM_ENTRY(MethodKind, PureVirtual),
ENUM_ENTRY(MethodKind, PureIntroducingVirtual),
};
static const EnumEntry<uint8_t> PtrKindNames[] = {
ENUM_ENTRY(PointerKind, Near16),
ENUM_ENTRY(PointerKind, Far16),
ENUM_ENTRY(PointerKind, Huge16),
ENUM_ENTRY(PointerKind, BasedOnSegment),
ENUM_ENTRY(PointerKind, BasedOnValue),
ENUM_ENTRY(PointerKind, BasedOnSegmentValue),
ENUM_ENTRY(PointerKind, BasedOnAddress),
ENUM_ENTRY(PointerKind, BasedOnSegmentAddress),
ENUM_ENTRY(PointerKind, BasedOnType),
ENUM_ENTRY(PointerKind, BasedOnSelf),
ENUM_ENTRY(PointerKind, Near32),
ENUM_ENTRY(PointerKind, Far32),
ENUM_ENTRY(PointerKind, Near64),
};
static const EnumEntry<uint8_t> PtrModeNames[] = {
ENUM_ENTRY(PointerMode, Pointer),
ENUM_ENTRY(PointerMode, LValueReference),
ENUM_ENTRY(PointerMode, PointerToDataMember),
ENUM_ENTRY(PointerMode, PointerToMemberFunction),
ENUM_ENTRY(PointerMode, RValueReference),
};
static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
ENUM_ENTRY(PointerToMemberRepresentation, Unknown),
ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData),
ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData),
ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData),
ENUM_ENTRY(PointerToMemberRepresentation, GeneralData),
ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction),
ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction),
ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction),
ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction),
};
static const EnumEntry<uint16_t> TypeModifierNames[] = {
ENUM_ENTRY(ModifierOptions, Const),
ENUM_ENTRY(ModifierOptions, Volatile),
ENUM_ENTRY(ModifierOptions, Unaligned),
};
static const EnumEntry<uint8_t> CallingConventions[] = {
ENUM_ENTRY(CallingConvention, NearC),
ENUM_ENTRY(CallingConvention, FarC),
ENUM_ENTRY(CallingConvention, NearPascal),
ENUM_ENTRY(CallingConvention, FarPascal),
ENUM_ENTRY(CallingConvention, NearFast),
ENUM_ENTRY(CallingConvention, FarFast),
ENUM_ENTRY(CallingConvention, NearStdCall),
ENUM_ENTRY(CallingConvention, FarStdCall),
ENUM_ENTRY(CallingConvention, NearSysCall),
ENUM_ENTRY(CallingConvention, FarSysCall),
ENUM_ENTRY(CallingConvention, ThisCall),
ENUM_ENTRY(CallingConvention, MipsCall),
ENUM_ENTRY(CallingConvention, Generic),
ENUM_ENTRY(CallingConvention, AlphaCall),
ENUM_ENTRY(CallingConvention, PpcCall),
ENUM_ENTRY(CallingConvention, SHCall),
ENUM_ENTRY(CallingConvention, ArmCall),
ENUM_ENTRY(CallingConvention, AM33Call),
ENUM_ENTRY(CallingConvention, TriCall),
ENUM_ENTRY(CallingConvention, SH5Call),
ENUM_ENTRY(CallingConvention, M32RCall),
ENUM_ENTRY(CallingConvention, ClrCall),
ENUM_ENTRY(CallingConvention, Inline),
ENUM_ENTRY(CallingConvention, NearVector),
};
static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
ENUM_ENTRY(FunctionOptions, Constructor),
ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
};
#undef ENUM_ENTRY
static StringRef getLeafTypeName(TypeLeafKind LT) {
switch (LT) {
#define TYPE_RECORD(ename, value, name) \
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
default:
break;
}
return "UnknownLeaf";
}
Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
assert(!IsInFieldList);
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
W->startLine() << getLeafTypeName(Record.Type);
W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Type),
makeArrayRef(LeafTypeNames));
if (Record.Type == LF_FIELDLIST) {
// Record that we're in a field list so that members do not get assigned
// type indices.
IsInFieldList = true;
}
return Error::success();
}
Error CVTypeDumper::visitTypeEnd(CVRecord<TypeLeafKind> &Record) {
if (Record.Type == LF_FIELDLIST) {
assert(IsInFieldList);
IsInFieldList = false;
}
assert(!IsInFieldList);
// Record every type that is not a field list member, even if Name is empty.
// CVUDTNames is indexed by type index, and must have one entry for every
// type. Field list members are not recorded, and are only referenced by
// their containing field list record.
recordType(Name);
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
W->unindent();
W->startLine() << "}\n";
return Error::success();
}
Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) {
assert(IsInFieldList);
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
W->startLine() << getLeafTypeName(Record.Kind);
W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Kind),
makeArrayRef(LeafTypeNames));
return Error::success();
}
Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
assert(IsInFieldList);
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
W->unindent();
W->startLine() << "}\n";
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
FieldListRecord &FieldList) {
CVTypeVisitor Visitor(*this);
if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
return EC;
Name = "<field list>";
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
StringIdRecord &String) {
printTypeIndex("Id", String.getId());
W->printString("StringData", String.getString());
// Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
Name = String.getString();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
ArgListRecord &Args) {
auto Indices = Args.getIndices();
uint32_t Size = Indices.size();
W->printNumber("NumArgs", Size);
ListScope Arguments(*W, "Arguments");
SmallString<256> TypeName("(");
for (uint32_t I = 0; I < Size; ++I) {
printTypeIndex("ArgType", Indices[I]);
StringRef ArgTypeName = getTypeName(Indices[I]);
TypeName.append(ArgTypeName);
if (I + 1 != Size)
TypeName.append(", ");
}
TypeName.push_back(')');
Name = saveName(TypeName);
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
ClassRecord &Class) {
uint16_t Props = static_cast<uint16_t>(Class.getOptions());
W->printNumber("MemberCount", Class.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
printTypeIndex("FieldList", Class.getFieldList());
printTypeIndex("DerivedFrom", Class.getDerivationList());
printTypeIndex("VShape", Class.getVTableShape());
W->printNumber("SizeOf", Class.getSize());
W->printString("Name", Class.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Class.getUniqueName());
Name = Class.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
UnionRecord &Union) {
uint16_t Props = static_cast<uint16_t>(Union.getOptions());
W->printNumber("MemberCount", Union.getMemberCount());
W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
printTypeIndex("FieldList", Union.getFieldList());
W->printNumber("SizeOf", Union.getSize());
W->printString("Name", Union.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Union.getUniqueName());
Name = Union.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
EnumRecord &Enum) {
uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
W->printNumber("NumEnumerators", Enum.getMemberCount());
W->printFlags("Properties", uint16_t(Enum.getOptions()),
makeArrayRef(ClassOptionNames));
printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
printTypeIndex("FieldListType", Enum.getFieldList());
W->printString("Name", Enum.getName());
if (Props & uint16_t(ClassOptions::HasUniqueName))
W->printString("LinkageName", Enum.getUniqueName());
Name = Enum.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
ArrayRecord &AT) {
printTypeIndex("ElementType", AT.getElementType());
printTypeIndex("IndexType", AT.getIndexType());
W->printNumber("SizeOf", AT.getSize());
W->printString("Name", AT.getName());
Name = AT.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
VFTableRecord &VFT) {
printTypeIndex("CompleteClass", VFT.getCompleteClass());
printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
W->printString("VFTableName", VFT.getName());
for (auto N : VFT.getMethodNames())
W->printString("MethodName", N);
Name = VFT.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
MemberFuncIdRecord &Id) {
printTypeIndex("ClassType", Id.getClassType());
printTypeIndex("FunctionType", Id.getFunctionType());
W->printString("Name", Id.getName());
Name = Id.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
ProcedureRecord &Proc) {
printTypeIndex("ReturnType", Proc.getReturnType());
W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
makeArrayRef(CallingConventions));
W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
makeArrayRef(FunctionOptionEnum));
W->printNumber("NumParameters", Proc.getParameterCount());
printTypeIndex("ArgListType", Proc.getArgumentList());
StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
SmallString<256> TypeName(ReturnTypeName);
TypeName.push_back(' ');
TypeName.append(ArgListTypeName);
Name = saveName(TypeName);
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
MemberFunctionRecord &MF) {
printTypeIndex("ReturnType", MF.getReturnType());
printTypeIndex("ClassType", MF.getClassType());
printTypeIndex("ThisType", MF.getThisType());
W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
makeArrayRef(CallingConventions));
W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
makeArrayRef(FunctionOptionEnum));
W->printNumber("NumParameters", MF.getParameterCount());
printTypeIndex("ArgListType", MF.getArgumentList());
W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
StringRef ReturnTypeName = getTypeName(MF.getReturnType());
StringRef ClassTypeName = getTypeName(MF.getClassType());
StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
SmallString<256> TypeName(ReturnTypeName);
TypeName.push_back(' ');
TypeName.append(ClassTypeName);
TypeName.append("::");
TypeName.append(ArgListTypeName);
Name = saveName(TypeName);
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
MethodOverloadListRecord &MethodList) {
for (auto &M : MethodList.getMethods()) {
ListScope S(*W, "Method");
printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
printTypeIndex("Type", M.getType());
if (M.isIntroducingVirtual())
W->printHex("VFTableOffset", M.getVFTableOffset());
}
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
FuncIdRecord &Func) {
printTypeIndex("ParentScope", Func.getParentScope());
printTypeIndex("FunctionType", Func.getFunctionType());
W->printString("Name", Func.getName());
Name = Func.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
TypeServer2Record &TS) {
W->printBinary("Signature", TS.getGuid());
W->printNumber("Age", TS.getAge());
W->printString("Name", TS.getName());
Name = TS.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
PointerRecord &Ptr) {
printTypeIndex("PointeeType", Ptr.getReferentType());
W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
makeArrayRef(PtrKindNames));
W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
W->printNumber("IsFlat", Ptr.isFlat());
W->printNumber("IsConst", Ptr.isConst());
W->printNumber("IsVolatile", Ptr.isVolatile());
W->printNumber("IsUnaligned", Ptr.isUnaligned());
W->printNumber("SizeOf", Ptr.getSize());
if (Ptr.isPointerToMember()) {
const MemberPointerInfo &MI = Ptr.getMemberInfo();
printTypeIndex("ClassType", MI.getContainingType());
W->printEnum("Representation", uint16_t(MI.getRepresentation()),
makeArrayRef(PtrMemberRepNames));
StringRef PointeeName = getTypeName(Ptr.getReferentType());
StringRef ClassName = getTypeName(MI.getContainingType());
SmallString<256> TypeName(PointeeName);
TypeName.push_back(' ');
TypeName.append(ClassName);
TypeName.append("::*");
Name = saveName(TypeName);
} else {
SmallString<256> TypeName;
if (Ptr.isConst())
TypeName.append("const ");
if (Ptr.isVolatile())
TypeName.append("volatile ");
if (Ptr.isUnaligned())
TypeName.append("__unaligned ");
TypeName.append(getTypeName(Ptr.getReferentType()));
if (Ptr.getMode() == PointerMode::LValueReference)
TypeName.append("&");
else if (Ptr.getMode() == PointerMode::RValueReference)
TypeName.append("&&");
else if (Ptr.getMode() == PointerMode::Pointer)
TypeName.append("*");
if (!TypeName.empty())
Name = saveName(TypeName);
}
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
ModifierRecord &Mod) {
uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
printTypeIndex("ModifiedType", Mod.getModifiedType());
W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
StringRef ModifiedName = getTypeName(Mod.getModifiedType());
SmallString<256> TypeName;
if (Mods & uint16_t(ModifierOptions::Const))
TypeName.append("const ");
if (Mods & uint16_t(ModifierOptions::Volatile))
TypeName.append("volatile ");
if (Mods & uint16_t(ModifierOptions::Unaligned))
TypeName.append("__unaligned ");
TypeName.append(ModifiedName);
Name = saveName(TypeName);
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
BitFieldRecord &BitField) {
printTypeIndex("Type", BitField.getType());
W->printNumber("BitSize", BitField.getBitSize());
W->printNumber("BitOffset", BitField.getBitOffset());
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
VFTableShapeRecord &Shape) {
W->printNumber("VFEntryCount", Shape.getEntryCount());
Name = saveName("<vftable " + utostr(Shape.getEntryCount()) + " methods>");
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
UdtSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
UdtModSourceLineRecord &Line) {
printTypeIndex("UDT", Line.getUDT());
printTypeIndex("SourceFile", Line.getSourceFile());
W->printNumber("LineNumber", Line.getLineNumber());
W->printNumber("Module", Line.getModule());
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
BuildInfoRecord &Args) {
W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
ListScope Arguments(*W, "Arguments");
for (auto Arg : Args.getArgs()) {
printTypeIndex("ArgType", Arg);
}
return Error::success();
}
void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
Attrs.getFlags());
}
void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
MethodOptions Options) {
W->printEnum("AccessSpecifier", uint8_t(Access),
makeArrayRef(MemberAccessNames));
// Data members will be vanilla. Don't try to print a method kind for them.
if (Kind != MethodKind::Vanilla)
W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
if (Options != MethodOptions::None) {
W->printFlags("MethodOptions", unsigned(Options),
makeArrayRef(MethodOptionNames));
}
}
Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) {
W->printHex("UnknownMember", unsigned(Record.Kind));
return Error::success();
}
Error CVTypeDumper::visitUnknownType(CVRecord<TypeLeafKind> &Record) {
W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
W->printNumber("Length", uint32_t(Record.content().size()));
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Nested) {
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
Name = Nested.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
OneMethodRecord &Method) {
MethodKind K = Method.getMethodKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
printTypeIndex("Type", Method.getType());
// If virtual, then read the vftable offset.
if (Method.isIntroducingVirtual())
W->printHex("VFTableOffset", Method.getVFTableOffset());
W->printString("Name", Method.getName());
Name = Method.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
OverloadedMethodRecord &Method) {
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
W->printString("Name", Method.getName());
Name = Method.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
DataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printHex("FieldOffset", Field.getFieldOffset());
W->printString("Name", Field.getName());
Name = Field.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
StaticDataMemberRecord &Field) {
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
W->printString("Name", Field.getName());
Name = Field.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
VFPtrRecord &VFTable) {
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
EnumeratorRecord &Enum) {
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
W->printNumber("EnumValue", Enum.getValue());
W->printString("Name", Enum.getName());
Name = Enum.getName();
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
BaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
W->printHex("BaseOffset", Base.getBaseOffset());
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
VirtualBaseClassRecord &Base) {
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
printTypeIndex("VBPtrType", Base.getVBPtrType());
W->printHex("VBPtrOffset", Base.getVBPtrOffset());
W->printHex("VBTableIndex", Base.getVTableIndex());
return Error::success();
}
Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
ListContinuationRecord &Cont) {
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();
}
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
if (TI.isNoneType())
return "<no type>";
if (TI.isSimple()) {
// This is a simple type.
for (const auto &SimpleTypeName : SimpleTypeNames) {
if (SimpleTypeName.Value == TI.getSimpleKind()) {
if (TI.getSimpleMode() == SimpleTypeMode::Direct)
return SimpleTypeName.Name.drop_back(1);
// Otherwise, this is a pointer type. We gloss over the distinction
// between near, far, 64, 32, etc, and just give a pointer type.
return SimpleTypeName.Name;
}
}
return "<unknown simple type>";
}
// User-defined type.
StringRef UDTName;
unsigned UDTIndex = TI.getIndex() - 0x1000;
if (UDTIndex < CVUDTNames.size())
return CVUDTNames[UDTIndex];
return "<unknown UDT>";
}
void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
StringRef TypeName;
if (!TI.isNoneType())
TypeName = getTypeName(TI);
if (!TypeName.empty())
W->printHex(FieldName, TypeName, TI.getIndex());
else
W->printHex(FieldName, TI.getIndex());
}
Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
assert(W && "printer should not be null");
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(*this);
CVTypeVisitor Visitor(Pipeline);
CVRecord<TypeLeafKind> RecordCopy = Record;
if (auto EC = Visitor.visitTypeRecord(RecordCopy))
return EC;
return Error::success();
}
Error CVTypeDumper::dump(const CVTypeArray &Types) {
assert(W && "printer should not be null");
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(*this);
CVTypeVisitor Visitor(Pipeline);
if (auto EC = Visitor.visitTypeStream(Types))
return EC;
return Error::success();
}
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
msf::ByteStream Stream(Data);
CVTypeArray Types;
msf::StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength()))
return EC;
return dump(Types);
}
void CVTypeDumper::setPrinter(ScopedPrinter *P) {
static ScopedPrinter NullP(llvm::nulls());
W = P ? P : &NullP;
}

View File

@ -1,86 +0,0 @@
; RUN: opt < %s -mtriple=aarch64 -interleaved-access -S | FileCheck %s
; CHECK-LABEL: @extract_user_basic(
; CHECK: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
; CHECK: %[[R:.+]] = extractvalue { <4 x i32>, <4 x i32> } %ldN, 0
; CHECK: extractelement <4 x i32> %[[R]], i64 1
define void @extract_user_basic(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
br i1 %C, label %if.then, label %if.merge
if.then:
%E = extractelement <8 x i32> %L, i32 2
br label %if.merge
if.merge:
ret void
}
; CHECK-LABEL: @extract_user_multi(
; CHECK: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
; CHECK: %[[R:.+]] = extractvalue { <4 x i32>, <4 x i32> } %ldN, 0
; CHECK: extractelement <4 x i32> %[[R]], i64 0
; CHECK: extractelement <4 x i32> %[[R]], i64 1
define void @extract_user_multi(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
br i1 %C, label %if.then, label %if.merge
if.then:
%E1 = extractelement <8 x i32> %L, i32 0
br label %if.merge
if.merge:
%E2 = extractelement <8 x i32> %L, i32 2
ret void
}
; CHECK-LABEL: @extract_user_multi_no_dom(
; CHECK-NOT: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
define void @extract_user_multi_no_dom(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%E1 = extractelement <8 x i32> %L, i32 0
br i1 %C, label %if.then, label %if.merge
if.then:
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E2 = extractelement <8 x i32> %L, i32 2
br label %if.merge
if.merge:
ret void
}
; CHECK-LABEL: @extract_user_wrong_const_index(
; CHECK-NOT: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
define void @extract_user_wrong_const_index(<8 x i32>* %A) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 1
ret void
}
; CHECK-LABEL: @extract_user_undef_index(
; CHECK-NOT: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
define void @extract_user_undef_index(<8 x i32>* %A) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 undef
ret void
}
; CHECK-LABEL: @extract_user_var_index(
; CHECK-NOT: %ldN = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32
define void @extract_user_var_index(<8 x i32>* %A, i32 %I) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 %I
ret void
}

View File

@ -1,393 +0,0 @@
; RUN: llc -mtriple=aarch64 -lower-interleaved-accesses=true < %s | FileCheck %s -check-prefix=NEON
; RUN: llc -mtriple=aarch64 -lower-interleaved-accesses=true -mattr=-neon < %s | FileCheck %s -check-prefix=NONEON
; NEON-LABEL: load_factor2:
; NEON: ld2 { v0.8b, v1.8b }, [x0]
; NONEON-LABEL: load_factor2:
; NONEON-NOT: ld2
define <8 x i8> @load_factor2(<16 x i8>* %ptr) {
%wide.vec = load <16 x i8>, <16 x i8>* %ptr, align 4
%strided.v0 = shufflevector <16 x i8> %wide.vec, <16 x i8> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%strided.v1 = shufflevector <16 x i8> %wide.vec, <16 x i8> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%add = add nsw <8 x i8> %strided.v0, %strided.v1
ret <8 x i8> %add
}
; NEON-LABEL: load_factor3:
; NEON: ld3 { v0.4s, v1.4s, v2.4s }, [x0]
; NONEON-LABEL: load_factor3:
; NONEON-NOT: ld3
define <4 x i32> @load_factor3(i32* %ptr) {
%base = bitcast i32* %ptr to <12 x i32>*
%wide.vec = load <12 x i32>, <12 x i32>* %base, align 4
%strided.v2 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 5, i32 8, i32 11>
%strided.v1 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
%add = add nsw <4 x i32> %strided.v2, %strided.v1
ret <4 x i32> %add
}
; NEON-LABEL: load_factor4:
; NEON: ld4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x0]
; NONEON-LABEL: load_factor4:
; NONEON-NOT: ld4
define <4 x i32> @load_factor4(i32* %ptr) {
%base = bitcast i32* %ptr to <16 x i32>*
%wide.vec = load <16 x i32>, <16 x i32>* %base, align 4
%strided.v0 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
%strided.v2 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
%add = add nsw <4 x i32> %strided.v0, %strided.v2
ret <4 x i32> %add
}
; NEON-LABEL: store_factor2:
; NEON: st2 { v0.8b, v1.8b }, [x0]
; NONEON-LABEL: store_factor2:
; NONEON-NOT: st2
define void @store_factor2(<16 x i8>* %ptr, <8 x i8> %v0, <8 x i8> %v1) {
%interleaved.vec = shufflevector <8 x i8> %v0, <8 x i8> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %interleaved.vec, <16 x i8>* %ptr, align 4
ret void
}
; NEON-LABEL: store_factor3:
; NEON: st3 { v0.4s, v1.4s, v2.4s }, [x0]
; NONEON-LABEL: store_factor3:
; NONEON-NOT: st3
define void @store_factor3(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
%base = bitcast i32* %ptr to <12 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_u = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_u, <12 x i32> <i32 0, i32 4, i32 8, i32 1, i32 5, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
store <12 x i32> %interleaved.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_factor4:
; NEON: st4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x0]
; NONEON-LABEL: store_factor4:
; NONEON-NOT: st4
define void @store_factor4(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
%base = bitcast i32* %ptr to <16 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_v3 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_v3, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
store <16 x i32> %interleaved.vec, <16 x i32>* %base, align 4
ret void
}
; The following cases test that interleaved access of pointer vectors can be
; matched to ldN/stN instruction.
; NEON-LABEL: load_ptrvec_factor2:
; NEON: ld2 { v0.2d, v1.2d }, [x0]
; NONEON-LABEL: load_ptrvec_factor2:
; NONEON-NOT: ld2
define <2 x i32*> @load_ptrvec_factor2(i32** %ptr) {
%base = bitcast i32** %ptr to <4 x i32*>*
%wide.vec = load <4 x i32*>, <4 x i32*>* %base, align 4
%strided.v0 = shufflevector <4 x i32*> %wide.vec, <4 x i32*> undef, <2 x i32> <i32 0, i32 2>
ret <2 x i32*> %strided.v0
}
; NEON-LABEL: load_ptrvec_factor3:
; NEON: ld3 { v0.2d, v1.2d, v2.2d }, [x0]
; NONEON-LABEL: load_ptrvec_factor3:
; NONEON-NOT: ld3
define void @load_ptrvec_factor3(i32** %ptr, <2 x i32*>* %ptr1, <2 x i32*>* %ptr2) {
%base = bitcast i32** %ptr to <6 x i32*>*
%wide.vec = load <6 x i32*>, <6 x i32*>* %base, align 4
%strided.v2 = shufflevector <6 x i32*> %wide.vec, <6 x i32*> undef, <2 x i32> <i32 2, i32 5>
store <2 x i32*> %strided.v2, <2 x i32*>* %ptr1
%strided.v1 = shufflevector <6 x i32*> %wide.vec, <6 x i32*> undef, <2 x i32> <i32 1, i32 4>
store <2 x i32*> %strided.v1, <2 x i32*>* %ptr2
ret void
}
; NEON-LABEL: load_ptrvec_factor4:
; NEON: ld4 { v0.2d, v1.2d, v2.2d, v3.2d }, [x0]
; NONEON-LABEL: load_ptrvec_factor4:
; NONEON-NOT: ld4
define void @load_ptrvec_factor4(i32** %ptr, <2 x i32*>* %ptr1, <2 x i32*>* %ptr2) {
%base = bitcast i32** %ptr to <8 x i32*>*
%wide.vec = load <8 x i32*>, <8 x i32*>* %base, align 4
%strided.v1 = shufflevector <8 x i32*> %wide.vec, <8 x i32*> undef, <2 x i32> <i32 1, i32 5>
%strided.v3 = shufflevector <8 x i32*> %wide.vec, <8 x i32*> undef, <2 x i32> <i32 3, i32 7>
store <2 x i32*> %strided.v1, <2 x i32*>* %ptr1
store <2 x i32*> %strided.v3, <2 x i32*>* %ptr2
ret void
}
; NEON-LABEL: store_ptrvec_factor2:
; NEON: st2 { v0.2d, v1.2d }, [x0]
; NONEON-LABEL: store_ptrvec_factor2:
; NONEON-NOT: st2
define void @store_ptrvec_factor2(i32** %ptr, <2 x i32*> %v0, <2 x i32*> %v1) {
%base = bitcast i32** %ptr to <4 x i32*>*
%interleaved.vec = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
store <4 x i32*> %interleaved.vec, <4 x i32*>* %base, align 4
ret void
}
; NEON-LABEL: store_ptrvec_factor3:
; NEON: st3 { v0.2d, v1.2d, v2.2d }, [x0]
; NONEON-LABEL: store_ptrvec_factor3:
; NONEON-NOT: st3
define void @store_ptrvec_factor3(i32** %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2) {
%base = bitcast i32** %ptr to <6 x i32*>*
%v0_v1 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%v2_u = shufflevector <2 x i32*> %v2, <2 x i32*> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
%interleaved.vec = shufflevector <4 x i32*> %v0_v1, <4 x i32*> %v2_u, <6 x i32> <i32 0, i32 2, i32 4, i32 1, i32 3, i32 5>
store <6 x i32*> %interleaved.vec, <6 x i32*>* %base, align 4
ret void
}
; NEON-LABEL: store_ptrvec_factor4:
; NEON: st4 { v0.2d, v1.2d, v2.2d, v3.2d }, [x0]
; NONEON-LABEL: store_ptrvec_factor4:
; NONEON-NOT: st4
define void @store_ptrvec_factor4(i32* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2, <2 x i32*> %v3) {
%base = bitcast i32* %ptr to <8 x i32*>*
%v0_v1 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%v2_v3 = shufflevector <2 x i32*> %v2, <2 x i32*> %v3, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%interleaved.vec = shufflevector <4 x i32*> %v0_v1, <4 x i32*> %v2_v3, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
store <8 x i32*> %interleaved.vec, <8 x i32*>* %base, align 4
ret void
}
; Following cases check that shuffle maskes with undef indices can be matched
; into ldN/stN instruction.
; NEON-LABEL: load_undef_mask_factor2:
; NEON: ld2 { v0.4s, v1.4s }, [x0]
; NONEON-LABEL: load_undef_mask_factor2:
; NONEON-NOT: ld2
define <4 x i32> @load_undef_mask_factor2(i32* %ptr) {
%base = bitcast i32* %ptr to <8 x i32>*
%wide.vec = load <8 x i32>, <8 x i32>* %base, align 4
%strided.v0 = shufflevector <8 x i32> %wide.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 2, i32 undef, i32 6>
%strided.v1 = shufflevector <8 x i32> %wide.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 3, i32 undef, i32 7>
%add = add nsw <4 x i32> %strided.v0, %strided.v1
ret <4 x i32> %add
}
; NEON-LABEL: load_undef_mask_factor3:
; NEON: ld3 { v0.4s, v1.4s, v2.4s }, [x0]
; NONEON-LABEL: load_undef_mask_factor3:
; NONEON-NOT: ld3
define <4 x i32> @load_undef_mask_factor3(i32* %ptr) {
%base = bitcast i32* %ptr to <12 x i32>*
%wide.vec = load <12 x i32>, <12 x i32>* %base, align 4
%strided.v2 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 undef, i32 undef>
%strided.v1 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
%add = add nsw <4 x i32> %strided.v2, %strided.v1
ret <4 x i32> %add
}
; NEON-LABEL: load_undef_mask_factor4:
; NEON: ld4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x0]
; NONEON-LABEL: load_undef_mask_factor4:
; NONEON-NOT: ld4
define <4 x i32> @load_undef_mask_factor4(i32* %ptr) {
%base = bitcast i32* %ptr to <16 x i32>*
%wide.vec = load <16 x i32>, <16 x i32>* %base, align 4
%strided.v0 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 undef, i32 undef>
%strided.v2 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 undef, i32 undef>
%add = add nsw <4 x i32> %strided.v0, %strided.v2
ret <4 x i32> %add
}
; NEON-LABEL: store_undef_mask_factor2:
; NEON: st2 { v0.4s, v1.4s }, [x0]
; NONEON-LABEL: store_undef_mask_factor2:
; NONEON-NOT: st2
define void @store_undef_mask_factor2(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%interleaved.vec = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 2, i32 6, i32 3, i32 7>
store <8 x i32> %interleaved.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_undef_mask_factor3:
; NEON: st3 { v0.4s, v1.4s, v2.4s }, [x0]
; NONEON-LABEL: store_undef_mask_factor3:
; NONEON-NOT: st3
define void @store_undef_mask_factor3(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
%base = bitcast i32* %ptr to <12 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_u = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_u, <12 x i32> <i32 0, i32 4, i32 undef, i32 1, i32 undef, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
store <12 x i32> %interleaved.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_undef_mask_factor4:
; NEON: st4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x0]
; NONEON-LABEL: store_undef_mask_factor4:
; NONEON-NOT: st4
define void @store_undef_mask_factor4(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
%base = bitcast i32* %ptr to <16 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_v3 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_v3, <16 x i32> <i32 0, i32 4, i32 8, i32 undef, i32 undef, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
store <16 x i32> %interleaved.vec, <16 x i32>* %base, align 4
ret void
}
; Check that we do something sane with illegal types.
; NEON-LABEL: load_illegal_factor2:
; NEON: BB#0:
; NEON-NEXT: ldr q[[V:[0-9]+]], [x0]
; NEON-NEXT: uzp1 v0.4s, v[[V]].4s, v{{.*}}.4s
; NEON-NEXT: ret
; NONEON-LABEL: load_illegal_factor2:
; NONEON: BB#0:
; NONEON-NEXT: ldr s0, [x0]
; NONEON-NEXT: ldr s1, [x0, #8]
; NONEON-NEXT: ret
define <3 x float> @load_illegal_factor2(<3 x float>* %p) nounwind {
%tmp1 = load <3 x float>, <3 x float>* %p, align 16
%tmp2 = shufflevector <3 x float> %tmp1, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
ret <3 x float> %tmp2
}
; NEON-LABEL: store_illegal_factor2:
; NEON: BB#0:
; NEON-NEXT: uzp1 v0.4s, v0.4s, v{{.*}}.4s
; NEON-NEXT: st1 { v0.d }[0], [x0]
; NEON-NEXT: ret
; NONEON-LABEL: store_illegal_factor2:
; NONEON: BB#0:
; NONEON-NEXT: fmov w[[ELT2:[0-9]+]], s2
; NONEON-NEXT: fmov w[[RES:[0-9]+]], s0
; NONEON-NEXT: bfi x[[RES]], x[[ELT2]], #32, #32
; NONEON-NEXT: str x[[RES]], [x0]
; NONEON-NEXT: ret
define void @store_illegal_factor2(<3 x float>* %p, <3 x float> %v) nounwind {
%tmp1 = shufflevector <3 x float> %v, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
store <3 x float> %tmp1, <3 x float>* %p, align 16
ret void
}
; NEON-LABEL: load_factor2_with_extract_user:
; NEON: ld2 { v0.4s, v1.4s }, [x0]
; NEON: mov w0, v0.s[1]
; NONEON-LABEL: load_factor2_with_extract_user:
; NONEON-NOT: ld2
define i32 @load_factor2_with_extract_user(<8 x i32>* %a) {
%1 = load <8 x i32>, <8 x i32>* %a, align 8
%2 = shufflevector <8 x i32> %1, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%3 = extractelement <8 x i32> %1, i32 2
ret i32 %3
}
; NEON-LABEL: store_general_mask_factor4:
; NEON: st4 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor4:
; NONEON-NOT: st4
define void @store_general_mask_factor4(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefbeg:
; NEON: st4 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor4_undefbeg:
; NONEON-NOT: st4
define void @store_general_mask_factor4_undefbeg(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 undef, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefend:
; NEON: st4 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor4_undefend:
; NONEON-NOT: st4
define void @store_general_mask_factor4_undefend(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 undef>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefmid:
; NEON: st4 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor4_undefmid:
; NONEON-NOT: st4
define void @store_general_mask_factor4_undefmid(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 32, i32 8, i32 5, i32 17, i32 undef, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefmulti:
; NEON: st4 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor4_undefmulti:
; NONEON-NOT: st4
define void @store_general_mask_factor4_undefmulti(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 undef, i32 8, i32 undef, i32 undef, i32 undef, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3:
; NEON: st3 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor3:
; NONEON-NOT: st3
define void @store_general_mask_factor3(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 5, i32 33, i32 17, i32 6, i32 34, i32 18, i32 7, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undefmultimid:
; NEON: st3 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor3_undefmultimid:
; NONEON-NOT: st3
define void @store_general_mask_factor3_undefmultimid(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undef_fail:
; NEON-NOT: st3
; NONEON-LABEL: store_general_mask_factor3_undef_fail:
; NONEON-NOT: st3
define void @store_general_mask_factor3_undef_fail(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 8, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undeflane:
; NEON: st3 { v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s, v{{[0-9]+}}.{{[0-9]+}}s }, [x0]
; NONEON-LABEL: store_general_mask_factor3_undeflane:
; NONEON-NOT: st3
define void @store_general_mask_factor3_undeflane(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_negativestart:
; NEON-NOT: st3
; NONEON-LABEL: store_general_mask_factor3_negativestart:
; NONEON-NOT: st3
define void @store_general_mask_factor3_negativestart(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 2, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}

View File

@ -1,133 +0,0 @@
# RUN: llc -run-pass=aarch64-ldst-opt %s -o - 2>&1 | FileCheck %s
--- |
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
; Function Attrs: nounwind
define i16 @promote-load-from-store(i32* %dst, i32 %x) #0 {
store i32 %x, i32* %dst
%dst16 = bitcast i32* %dst to i16*
%dst1 = getelementptr inbounds i16, i16* %dst16, i32 1
%x16 = load i16, i16* %dst1
ret i16 %x16
}
; Function Attrs: nounwind
define void @store-pair(i32* %dst, i32 %x, i32 %y) #0 {
%dst01 = bitcast i32* %dst to i32*
%dst1 = getelementptr inbounds i32, i32* %dst, i32 1
store i32 %x, i32* %dst01
store i32 %x, i32* %dst1
ret void
}
attributes #0 = { nounwind }
...
---
name: promote-load-from-store
alignment: 2
exposesReturnsTwice: false
tracksRegLiveness: true
liveins:
- { reg: '%x0' }
- { reg: '%w1' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 0
adjustsStack: false
hasCalls: false
maxCallFrameSize: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
body: |
bb.0 (%ir-block.0):
liveins: %w1, %x0, %lr
STRWui killed %w1, %x0, 0 :: (store 4 into %ir.dst)
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
%w0 = LDRHHui killed %x0, 1 :: (load 2 from %ir.dst1)
RET %lr, implicit %w0
...
# CHECK-LABEL: name: promote-load-from-store
# CHECK: STRWui %w1
# CHECK: UBFMWri %w1
---
name: store-pair
alignment: 2
exposesReturnsTwice: false
tracksRegLiveness: true
liveins:
- { reg: '%x0' }
- { reg: '%w1' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 0
adjustsStack: false
hasCalls: false
maxCallFrameSize: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
body: |
bb.0 (%ir-block.0):
liveins: %w1, %x0, %lr
STRWui %w1, %x0, 0 :: (store 4 into %ir.dst01)
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
CFI_INSTRUCTION 0
STRWui killed %w1, killed %x0, 1 :: (store 4 into %ir.dst1)
RET %lr
...
# CHECK-LABEL: name: store-pair
# CHECK: STPWi

View File

@ -1,26 +0,0 @@
; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=kaveri -mattr=+flat-for-global < %s | FileCheck -check-prefix=HSA -check-prefix=HSA-DEFAULT -check-prefix=ALL %s
; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=kaveri -mattr=-flat-for-global < %s | FileCheck -check-prefix=HSA -check-prefix=HSA-NODEFAULT -check-prefix=ALL %s
; RUN: llc -mtriple=amdgcn-- -mcpu=kaveri -mattr=-flat-for-global < %s | FileCheck -check-prefix=NOHSA-DEFAULT -check-prefix=ALL %s
; RUN: llc -mtriple=amdgcn-- -mcpu=kaveri -mattr=+flat-for-global < %s | FileCheck -check-prefix=NOHSA-NODEFAULT -check-prefix=ALL %s
; There are no stack objects even though flat is used by default, so
; flat_scratch_init should be disabled.
; ALL-LABEL: {{^}}test:
; HSA: .amd_kernel_code_t
; HSA: enable_sgpr_flat_scratch_init = 0
; HSA: .end_amd_kernel_code_t
; ALL-NOT: flat_scr
; HSA-DEFAULT: flat_store_dword
; HSA-NODEFAULT: buffer_store_dword
; NOHSA-DEFAULT: buffer_store_dword
; NOHSA-NODEFAULT: flat_store_dword
define void @test(i32 addrspace(1)* %out) {
entry:
store i32 0, i32 addrspace(1)* %out
ret void
}

View File

@ -1,29 +0,0 @@
; RUN: llc -march=amdgcn -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI %s
; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=SI %s
declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone
declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone
; SI-LABEL: {{^}}test_convert_fp16_to_fp32:
; SI: buffer_load_ushort [[VAL:v[0-9]+]]
; SI: v_cvt_f32_f16_e32 [[RESULT:v[0-9]+]], [[VAL]]
; SI: buffer_store_dword [[RESULT]]
define void @test_convert_fp16_to_fp32(float addrspace(1)* noalias %out, i16 addrspace(1)* noalias %in) nounwind {
%val = load i16, i16 addrspace(1)* %in, align 2
%cvt = call float @llvm.convert.from.fp16.f32(i16 %val) nounwind readnone
store float %cvt, float addrspace(1)* %out, align 4
ret void
}
; SI-LABEL: {{^}}test_convert_fp16_to_fp64:
; SI: buffer_load_ushort [[VAL:v[0-9]+]]
; SI: v_cvt_f32_f16_e32 [[RESULT32:v[0-9]+]], [[VAL]]
; SI: v_cvt_f64_f32_e32 [[RESULT:v\[[0-9]+:[0-9]+\]]], [[RESULT32]]
; SI: buffer_store_dwordx2 [[RESULT]]
define void @test_convert_fp16_to_fp64(double addrspace(1)* noalias %out, i16 addrspace(1)* noalias %in) nounwind {
%val = load i16, i16 addrspace(1)* %in, align 2
%cvt = call double @llvm.convert.from.fp16.f64(i16 %val) nounwind readnone
store double %cvt, double addrspace(1)* %out, align 4
ret void
}

View File

@ -1,86 +0,0 @@
; RUN: opt < %s -mtriple=arm-eabi -mattr=+neon -interleaved-access -S | FileCheck %s
; CHECK-LABEL: @extract_user_basic(
; CHECK: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
; CHECK: %[[R:.+]] = extractvalue { <4 x i32>, <4 x i32> } %vldN, 0
; CHECK: extractelement <4 x i32> %[[R]], i64 1
define void @extract_user_basic(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
br i1 %C, label %if.then, label %if.merge
if.then:
%E = extractelement <8 x i32> %L, i32 2
br label %if.merge
if.merge:
ret void
}
; CHECK-LABEL: @extract_user_multi(
; CHECK: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
; CHECK: %[[R:.+]] = extractvalue { <4 x i32>, <4 x i32> } %vldN, 0
; CHECK: extractelement <4 x i32> %[[R]], i64 0
; CHECK: extractelement <4 x i32> %[[R]], i64 1
define void @extract_user_multi(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
br i1 %C, label %if.then, label %if.merge
if.then:
%E1 = extractelement <8 x i32> %L, i32 0
br label %if.merge
if.merge:
%E2 = extractelement <8 x i32> %L, i32 2
ret void
}
; CHECK-LABEL: @extract_user_multi_no_dom(
; CHECK-NOT: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
define void @extract_user_multi_no_dom(<8 x i32>* %A, i1 %C) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%E1 = extractelement <8 x i32> %L, i32 0
br i1 %C, label %if.then, label %if.merge
if.then:
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E2 = extractelement <8 x i32> %L, i32 2
br label %if.merge
if.merge:
ret void
}
; CHECK-LABEL: @extract_user_wrong_const_index(
; CHECK-NOT: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
define void @extract_user_wrong_const_index(<8 x i32>* %A) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 1
ret void
}
; CHECK-LABEL: @extract_user_undef_index(
; CHECK-NOT: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
define void @extract_user_undef_index(<8 x i32>* %A) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 undef
ret void
}
; CHECK-LABEL: @extract_user_var_index(
; CHECK-NOT: %vldN = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8
define void @extract_user_var_index(<8 x i32>* %A, i32 %I) {
entry:
%L = load <8 x i32>, <8 x i32>* %A, align 8
%S = shufflevector <8 x i32> %L, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%E = extractelement <8 x i32> %L, i32 %I
ret void
}

View File

@ -1,462 +0,0 @@
; RUN: llc -mtriple=arm-eabi -mattr=+neon -lower-interleaved-accesses=true < %s | FileCheck %s -check-prefix=NEON
; RUN: llc -mtriple=arm-eabi -mattr=-neon -lower-interleaved-accesses=true < %s | FileCheck %s -check-prefix=NONEON
; NEON-LABEL: load_factor2:
; NEON: vld2.8 {d16, d17}, [r0]
; NONEON-LABEL: load_factor2:
; NONEON-NOT: vld2
define <8 x i8> @load_factor2(<16 x i8>* %ptr) {
%wide.vec = load <16 x i8>, <16 x i8>* %ptr, align 4
%strided.v0 = shufflevector <16 x i8> %wide.vec, <16 x i8> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%strided.v1 = shufflevector <16 x i8> %wide.vec, <16 x i8> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%add = add nsw <8 x i8> %strided.v0, %strided.v1
ret <8 x i8> %add
}
; NEON-LABEL: load_factor3:
; NEON: vld3.32 {d16, d17, d18}, [r0]
; NONEON-LABEL: load_factor3:
; NONEON-NOT: vld3
define <2 x i32> @load_factor3(i32* %ptr) {
%base = bitcast i32* %ptr to <6 x i32>*
%wide.vec = load <6 x i32>, <6 x i32>* %base, align 4
%strided.v2 = shufflevector <6 x i32> %wide.vec, <6 x i32> undef, <2 x i32> <i32 2, i32 5>
%strided.v1 = shufflevector <6 x i32> %wide.vec, <6 x i32> undef, <2 x i32> <i32 1, i32 4>
%add = add nsw <2 x i32> %strided.v2, %strided.v1
ret <2 x i32> %add
}
; NEON-LABEL: load_factor4:
; NEON: vld4.32 {d16, d18, d20, d22}, [r0]!
; NEON: vld4.32 {d17, d19, d21, d23}, [r0]
; NONEON-LABEL: load_factor4:
; NONEON-NOT: vld4
define <4 x i32> @load_factor4(i32* %ptr) {
%base = bitcast i32* %ptr to <16 x i32>*
%wide.vec = load <16 x i32>, <16 x i32>* %base, align 4
%strided.v0 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
%strided.v2 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
%add = add nsw <4 x i32> %strided.v0, %strided.v2
ret <4 x i32> %add
}
; NEON-LABEL: store_factor2:
; NEON: vst2.8 {d16, d17}, [r0]
; NONEON-LABEL: store_factor2:
; NONEON-NOT: vst2
define void @store_factor2(<16 x i8>* %ptr, <8 x i8> %v0, <8 x i8> %v1) {
%interleaved.vec = shufflevector <8 x i8> %v0, <8 x i8> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %interleaved.vec, <16 x i8>* %ptr, align 4
ret void
}
; NEON-LABEL: store_factor3:
; NEON: vst3.32 {d16, d18, d20}, [r0]!
; NEON: vst3.32 {d17, d19, d21}, [r0]
; NONEON-LABEL: store_factor3:
; NONEON-NOT: vst3.32
define void @store_factor3(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
%base = bitcast i32* %ptr to <12 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_u = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_u, <12 x i32> <i32 0, i32 4, i32 8, i32 1, i32 5, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
store <12 x i32> %interleaved.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_factor4:
; NEON: vst4.32 {d16, d18, d20, d22}, [r0]!
; NEON: vst4.32 {d17, d19, d21, d23}, [r0]
; NONEON-LABEL: store_factor4:
; NONEON-NOT: vst4
define void @store_factor4(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
%base = bitcast i32* %ptr to <16 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_v3 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_v3, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
store <16 x i32> %interleaved.vec, <16 x i32>* %base, align 4
ret void
}
; The following cases test that interleaved access of pointer vectors can be
; matched to ldN/stN instruction.
; NEON-LABEL: load_ptrvec_factor2:
; NEON: vld2.32 {d16, d17}, [r0]
; NONEON-LABEL: load_ptrvec_factor2:
; NONEON-NOT: vld2
define <2 x i32*> @load_ptrvec_factor2(i32** %ptr) {
%base = bitcast i32** %ptr to <4 x i32*>*
%wide.vec = load <4 x i32*>, <4 x i32*>* %base, align 4
%strided.v0 = shufflevector <4 x i32*> %wide.vec, <4 x i32*> undef, <2 x i32> <i32 0, i32 2>
ret <2 x i32*> %strided.v0
}
; NEON-LABEL: load_ptrvec_factor3:
; NEON: vld3.32 {d16, d17, d18}, [r0]
; NONEON-LABEL: load_ptrvec_factor3:
; NONEON-NOT: vld3
define void @load_ptrvec_factor3(i32** %ptr, <2 x i32*>* %ptr1, <2 x i32*>* %ptr2) {
%base = bitcast i32** %ptr to <6 x i32*>*
%wide.vec = load <6 x i32*>, <6 x i32*>* %base, align 4
%strided.v2 = shufflevector <6 x i32*> %wide.vec, <6 x i32*> undef, <2 x i32> <i32 2, i32 5>
store <2 x i32*> %strided.v2, <2 x i32*>* %ptr1
%strided.v1 = shufflevector <6 x i32*> %wide.vec, <6 x i32*> undef, <2 x i32> <i32 1, i32 4>
store <2 x i32*> %strided.v1, <2 x i32*>* %ptr2
ret void
}
; NEON-LABEL: load_ptrvec_factor4:
; NEON: vld4.32 {d16, d17, d18, d19}, [r0]
; NONEON-LABEL: load_ptrvec_factor4:
; NONEON-NOT: vld4
define void @load_ptrvec_factor4(i32** %ptr, <2 x i32*>* %ptr1, <2 x i32*>* %ptr2) {
%base = bitcast i32** %ptr to <8 x i32*>*
%wide.vec = load <8 x i32*>, <8 x i32*>* %base, align 4
%strided.v1 = shufflevector <8 x i32*> %wide.vec, <8 x i32*> undef, <2 x i32> <i32 1, i32 5>
%strided.v3 = shufflevector <8 x i32*> %wide.vec, <8 x i32*> undef, <2 x i32> <i32 3, i32 7>
store <2 x i32*> %strided.v1, <2 x i32*>* %ptr1
store <2 x i32*> %strided.v3, <2 x i32*>* %ptr2
ret void
}
; NEON-LABEL: store_ptrvec_factor2:
; NEON: vst2.32 {d16, d17}, [r0]
; NONEON-LABEL: store_ptrvec_factor2:
; NONEON-NOT: vst2
define void @store_ptrvec_factor2(i32** %ptr, <2 x i32*> %v0, <2 x i32*> %v1) {
%base = bitcast i32** %ptr to <4 x i32*>*
%interleaved.vec = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
store <4 x i32*> %interleaved.vec, <4 x i32*>* %base, align 4
ret void
}
; NEON-LABEL: store_ptrvec_factor3:
; NEON: vst3.32 {d16, d17, d18}, [r0]
; NONEON-LABEL: store_ptrvec_factor3:
; NONEON-NOT: vst3
define void @store_ptrvec_factor3(i32** %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2) {
%base = bitcast i32** %ptr to <6 x i32*>*
%v0_v1 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%v2_u = shufflevector <2 x i32*> %v2, <2 x i32*> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
%interleaved.vec = shufflevector <4 x i32*> %v0_v1, <4 x i32*> %v2_u, <6 x i32> <i32 0, i32 2, i32 4, i32 1, i32 3, i32 5>
store <6 x i32*> %interleaved.vec, <6 x i32*>* %base, align 4
ret void
}
; NEON-LABEL: store_ptrvec_factor4:
; NEON: vst4.32 {d16, d17, d18, d19}, [r0]
; NONEON-LABEL: store_ptrvec_factor4:
; NONEON-NOT: vst4
define void @store_ptrvec_factor4(i32* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2, <2 x i32*> %v3) {
%base = bitcast i32* %ptr to <8 x i32*>*
%v0_v1 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%v2_v3 = shufflevector <2 x i32*> %v2, <2 x i32*> %v3, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%interleaved.vec = shufflevector <4 x i32*> %v0_v1, <4 x i32*> %v2_v3, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
store <8 x i32*> %interleaved.vec, <8 x i32*>* %base, align 4
ret void
}
; Following cases check that shuffle maskes with undef indices can be matched
; into ldN/stN instruction.
; NEON-LABEL: load_undef_mask_factor2:
; NEON: vld2.32 {d16, d17, d18, d19}, [r0]
; NONEON-LABEL: load_undef_mask_factor2:
; NONEON-NOT: vld2
define <4 x i32> @load_undef_mask_factor2(i32* %ptr) {
%base = bitcast i32* %ptr to <8 x i32>*
%wide.vec = load <8 x i32>, <8 x i32>* %base, align 4
%strided.v0 = shufflevector <8 x i32> %wide.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 2, i32 undef, i32 6>
%strided.v1 = shufflevector <8 x i32> %wide.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 3, i32 undef, i32 7>
%add = add nsw <4 x i32> %strided.v0, %strided.v1
ret <4 x i32> %add
}
; NEON-LABEL: load_undef_mask_factor3:
; NEON: vld3.32 {d16, d18, d20}, [r0]!
; NEON: vld3.32 {d17, d19, d21}, [r0]
; NONEON-LABEL: load_undef_mask_factor3:
; NONEON-NOT: vld3
define <4 x i32> @load_undef_mask_factor3(i32* %ptr) {
%base = bitcast i32* %ptr to <12 x i32>*
%wide.vec = load <12 x i32>, <12 x i32>* %base, align 4
%strided.v2 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 undef, i32 undef>
%strided.v1 = shufflevector <12 x i32> %wide.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
%add = add nsw <4 x i32> %strided.v2, %strided.v1
ret <4 x i32> %add
}
; NEON-LABEL: load_undef_mask_factor4:
; NEON: vld4.32 {d16, d18, d20, d22}, [r0]!
; NEON: vld4.32 {d17, d19, d21, d23}, [r0]
; NONEON-LABEL: load_undef_mask_factor4:
; NONEON-NOT: vld4
define <4 x i32> @load_undef_mask_factor4(i32* %ptr) {
%base = bitcast i32* %ptr to <16 x i32>*
%wide.vec = load <16 x i32>, <16 x i32>* %base, align 4
%strided.v0 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 undef, i32 undef>
%strided.v2 = shufflevector <16 x i32> %wide.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 undef, i32 undef>
%add = add nsw <4 x i32> %strided.v0, %strided.v2
ret <4 x i32> %add
}
; NEON-LABEL: store_undef_mask_factor2:
; NEON: vst2.32 {d16, d17, d18, d19}, [r0]
; NONEON-LABEL: store_undef_mask_factor2:
; NONEON-NOT: vst2
define void @store_undef_mask_factor2(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%interleaved.vec = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 2, i32 6, i32 3, i32 7>
store <8 x i32> %interleaved.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_undef_mask_factor3:
; NEON: vst3.32 {d16, d18, d20}, [r0]!
; NEON: vst3.32 {d17, d19, d21}, [r0]
; NONEON-LABEL: store_undef_mask_factor3:
; NONEON-NOT: vst3
define void @store_undef_mask_factor3(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
%base = bitcast i32* %ptr to <12 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_u = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_u, <12 x i32> <i32 0, i32 4, i32 undef, i32 1, i32 undef, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
store <12 x i32> %interleaved.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_undef_mask_factor4:
; NEON: vst4.32 {d16, d18, d20, d22}, [r0]!
; NEON: vst4.32 {d17, d19, d21, d23}, [r0]
; NONEON-LABEL: store_undef_mask_factor4:
; NONEON-NOT: vst4
define void @store_undef_mask_factor4(i32* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
%base = bitcast i32* %ptr to <16 x i32>*
%v0_v1 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%v2_v3 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%interleaved.vec = shufflevector <8 x i32> %v0_v1, <8 x i32> %v2_v3, <16 x i32> <i32 0, i32 4, i32 8, i32 undef, i32 undef, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
store <16 x i32> %interleaved.vec, <16 x i32>* %base, align 4
ret void
}
; The following test cases check that address spaces are properly handled
; NEON-LABEL: load_address_space
; NEON: vld3.32
; NONEON-LABEL: load_address_space
; NONEON-NOT: vld3
define void @load_address_space(<4 x i32> addrspace(1)* %A, <2 x i32>* %B) {
%tmp = load <4 x i32>, <4 x i32> addrspace(1)* %A
%interleaved = shufflevector <4 x i32> %tmp, <4 x i32> undef, <2 x i32> <i32 0, i32 3>
store <2 x i32> %interleaved, <2 x i32>* %B
ret void
}
; NEON-LABEL: store_address_space
; NEON: vst2.32
; NONEON-LABEL: store_address_space
; NONEON-NOT: vst2
define void @store_address_space(<2 x i32>* %A, <2 x i32>* %B, <4 x i32> addrspace(1)* %C) {
%tmp0 = load <2 x i32>, <2 x i32>* %A
%tmp1 = load <2 x i32>, <2 x i32>* %B
%interleaved = shufflevector <2 x i32> %tmp0, <2 x i32> %tmp1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
store <4 x i32> %interleaved, <4 x i32> addrspace(1)* %C
ret void
}
; Check that we do something sane with illegal types.
; NEON-LABEL: load_illegal_factor2:
; NEON: BB#0:
; NEON-NEXT: vld1.64 {d16, d17}, [r0:128]
; NEON-NEXT: vuzp.32 q8, {{.*}}
; NEON-NEXT: vmov r0, r1, d16
; NEON-NEXT: vmov r2, r3, {{.*}}
; NEON-NEXT: mov pc, lr
; NONEON-LABEL: load_illegal_factor2:
; NONEON: BB#0:
; NONEON-NEXT: ldr [[ELT0:r[0-9]+]], [r0]
; NONEON-NEXT: ldr r1, [r0, #8]
; NONEON-NEXT: mov r0, [[ELT0]]
; NONEON-NEXT: mov pc, lr
define <3 x float> @load_illegal_factor2(<3 x float>* %p) nounwind {
%tmp1 = load <3 x float>, <3 x float>* %p, align 16
%tmp2 = shufflevector <3 x float> %tmp1, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
ret <3 x float> %tmp2
}
; This lowering isn't great, but it's at least correct.
; NEON-LABEL: store_illegal_factor2:
; NEON: BB#0:
; NEON-NEXT: vldr d17, [sp]
; NEON-NEXT: vmov d16, r2, r3
; NEON-NEXT: vuzp.32 q8, {{.*}}
; NEON-NEXT: vstr d16, [r0]
; NEON-NEXT: mov pc, lr
; NONEON-LABEL: store_illegal_factor2:
; NONEON: BB#0:
; NONEON-NEXT: stm r0, {r1, r3}
; NONEON-NEXT: mov pc, lr
define void @store_illegal_factor2(<3 x float>* %p, <3 x float> %v) nounwind {
%tmp1 = shufflevector <3 x float> %v, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
store <3 x float> %tmp1, <3 x float>* %p, align 16
ret void
}
; NEON-LABEL: load_factor2_with_extract_user:
; NEON: vld2.32 {d16, d17, d18, d19}, [r0:64]
; NEON: vmov.32 r0, d16[1]
; NONEON-LABEL: load_factor2_with_extract_user:
; NONEON-NOT: vld2
define i32 @load_factor2_with_extract_user(<8 x i32>* %a) {
%1 = load <8 x i32>, <8 x i32>* %a, align 8
%2 = shufflevector <8 x i32> %1, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
%3 = extractelement <8 x i32> %1, i32 2
ret i32 %3
}
; NEON-LABEL: store_general_mask_factor4:
; NEON: vst4.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor4:
; NONEON-NOT: vst4.32
define void @store_general_mask_factor4(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefbeg:
; NEON: vst4.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor4_undefbeg:
; NONEON-NOT: vst4.32
define void @store_general_mask_factor4_undefbeg(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 undef, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefend:
; NEON: vst4.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor4_undefend:
; NONEON-NOT: vst4.32
define void @store_general_mask_factor4_undefend(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 undef>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefmid:
; NEON: vst4.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor4_undefmid:
; NONEON-NOT: vst4.32
define void @store_general_mask_factor4_undefmid(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 32, i32 8, i32 5, i32 17, i32 undef, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor4_undefmulti:
; NEON: vst4.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor4_undefmulti:
; NONEON-NOT: vst4.32
define void @store_general_mask_factor4_undefmulti(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <8 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 undef, i32 8, i32 undef, i32 undef, i32 undef, i32 9>
store <8 x i32> %i.vec, <8 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3:
; NEON: vst3.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor3:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 5, i32 33, i32 17, i32 6, i32 34, i32 18, i32 7, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undefmultimid:
; NEON: vst3.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor3_undefmultimid:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_undefmultimid(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undef_fail:
; NEON-NOT: vst3.32
; NONEON-LABEL: store_general_mask_factor3_undef_fail:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_undef_fail(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 8, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_undeflane:
; NEON: vst3.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor3_undeflane:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_undeflane(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_endstart_fail:
; NEON-NOT: vst3.32
; NONEON-LABEL: store_general_mask_factor3_endstart_fail:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_endstart_fail(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 2, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_endstart_pass:
; NEON: vst3.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor3_endstart_pass:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_endstart_pass(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_midstart_fail:
; NEON-NOT: vst3.32
; NONEON-LABEL: store_general_mask_factor3_midstart_fail:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_midstart_fail(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 0, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}
; NEON-LABEL: store_general_mask_factor3_midstart_pass:
; NEON: vst3.32 {d{{[0-9]+}}, d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
; NONEON-LABEL: store_general_mask_factor3_midstart_pass:
; NONEON-NOT: vst3.32
define void @store_general_mask_factor3_midstart_pass(i32* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
%base = bitcast i32* %ptr to <12 x i32>*
%i.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 1, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
store <12 x i32> %i.vec, <12 x i32>* %base, align 4
ret void
}

View File

@ -1,51 +0,0 @@
; RUN: llc < %s -mcpu=atom -march=x86-64 | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
; Additional tests for 64-bit divide bypass
define i64 @Test_get_quotient(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: Test_get_quotient:
; CHECK: movq %rdi, %rax
; CHECK: orq %rsi, %rax
; CHECK-NEXT: testq $-65536, %rax
; CHECK-NEXT: je
; CHECK: idivq
; CHECK: ret
; CHECK: divw
; CHECK: ret
%result = sdiv i64 %a, %b
ret i64 %result
}
define i64 @Test_get_remainder(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: Test_get_remainder:
; CHECK: movq %rdi, %rax
; CHECK: orq %rsi, %rax
; CHECK-NEXT: testq $-65536, %rax
; CHECK-NEXT: je
; CHECK: idivq
; CHECK: ret
; CHECK: divw
; CHECK: ret
%result = srem i64 %a, %b
ret i64 %result
}
define i64 @Test_get_quotient_and_remainder(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: Test_get_quotient_and_remainder:
; CHECK: movq %rdi, %rax
; CHECK: orq %rsi, %rax
; CHECK-NEXT: testq $-65536, %rax
; CHECK-NEXT: je
; CHECK: idivq
; CHECK: divw
; CHECK: addq
; CHECK: ret
; CHECK-NOT: idivq
; CHECK-NOT: divw
%resultdiv = sdiv i64 %a, %b
%resultrem = srem i64 %a, %b
%result = add i64 %resultdiv, %resultrem
ret i64 %result
}

View File

@ -1,112 +0,0 @@
; RUN: llc < %s -mcpu=atom -mtriple=i686-linux | FileCheck %s
define i32 @Test_get_quotient(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: Test_get_quotient:
; CHECK: orl %ecx, %edx
; CHECK-NEXT: testl $-256, %edx
; CHECK-NEXT: je
; CHECK: idivl
; CHECK: ret
; CHECK: divb
; CHECK: ret
%result = sdiv i32 %a, %b
ret i32 %result
}
define i32 @Test_get_remainder(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: Test_get_remainder:
; CHECK: orl %ecx, %edx
; CHECK-NEXT: testl $-256, %edx
; CHECK-NEXT: je
; CHECK: idivl
; CHECK: ret
; CHECK: divb
; CHECK: ret
%result = srem i32 %a, %b
ret i32 %result
}
define i32 @Test_get_quotient_and_remainder(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: Test_get_quotient_and_remainder:
; CHECK: orl %ecx, %edx
; CHECK-NEXT: testl $-256, %edx
; CHECK-NEXT: je
; CHECK: idivl
; CHECK: divb
; CHECK: addl
; CHECK: ret
; CHECK-NOT: idivl
; CHECK-NOT: divb
%resultdiv = sdiv i32 %a, %b
%resultrem = srem i32 %a, %b
%result = add i32 %resultdiv, %resultrem
ret i32 %result
}
define i32 @Test_use_div_and_idiv(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: Test_use_div_and_idiv:
; CHECK: idivl
; CHECK: divb
; CHECK: divl
; CHECK: divb
; CHECK: addl
; CHECK: ret
%resultidiv = sdiv i32 %a, %b
%resultdiv = udiv i32 %a, %b
%result = add i32 %resultidiv, %resultdiv
ret i32 %result
}
define i32 @Test_use_div_imm_imm() nounwind {
; CHECK-LABEL: Test_use_div_imm_imm:
; CHECK: movl $64
%resultdiv = sdiv i32 256, 4
ret i32 %resultdiv
}
define i32 @Test_use_div_reg_imm(i32 %a) nounwind {
; CHECK-LABEL: Test_use_div_reg_imm:
; CHECK-NOT: test
; CHECK-NOT: idiv
; CHECK-NOT: divb
%resultdiv = sdiv i32 %a, 33
ret i32 %resultdiv
}
define i32 @Test_use_rem_reg_imm(i32 %a) nounwind {
; CHECK-LABEL: Test_use_rem_reg_imm:
; CHECK-NOT: test
; CHECK-NOT: idiv
; CHECK-NOT: divb
%resultrem = srem i32 %a, 33
ret i32 %resultrem
}
define i32 @Test_use_divrem_reg_imm(i32 %a) nounwind {
; CHECK-LABEL: Test_use_divrem_reg_imm:
; CHECK-NOT: test
; CHECK-NOT: idiv
; CHECK-NOT: divb
%resultdiv = sdiv i32 %a, 33
%resultrem = srem i32 %a, 33
%result = add i32 %resultdiv, %resultrem
ret i32 %result
}
define i32 @Test_use_div_imm_reg(i32 %a) nounwind {
; CHECK-LABEL: Test_use_div_imm_reg:
; CHECK: test
; CHECK: idiv
; CHECK: divb
%resultdiv = sdiv i32 4, %a
ret i32 %resultdiv
}
define i32 @Test_use_rem_imm_reg(i32 %a) nounwind {
; CHECK-LABEL: Test_use_rem_imm_reg:
; CHECK: test
; CHECK: idiv
; CHECK: divb
%resultdiv = sdiv i32 4, %a
ret i32 %resultdiv
}

View File

@ -1,43 +0,0 @@
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+idivl-to-divb < %s | FileCheck -check-prefix=DIV32 %s
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+idivq-to-divw < %s | FileCheck -check-prefix=DIV64 %s
define i32 @div32(i32 %a, i32 %b) {
entry:
; DIV32-LABEL: div32:
; DIV32: orl %{{.*}}, [[REG:%[a-z]+]]
; DIV32: testl $-256, [[REG]]
; DIV32: divb
; DIV64-LABEL: div32:
; DIV64-NOT: divb
%div = sdiv i32 %a, %b
ret i32 %div
}
define i64 @div64(i64 %a, i64 %b) {
entry:
; DIV32-LABEL: div64:
; DIV32-NOT: divw
; DIV64-LABEL: div64:
; DIV64: orq %{{.*}}, [[REG:%[a-z]+]]
; DIV64: testq $-65536, [[REG]]
; DIV64: divw
%div = sdiv i64 %a, %b
ret i64 %div
}
; Verify that no extra code is generated when optimizing for size.
define i32 @div32_optsize(i32 %a, i32 %b) optsize {
; DIV32-LABEL: div32_optsize:
; DIV32-NOT: divb
%div = sdiv i32 %a, %b
ret i32 %div
}
define i32 @div32_minsize(i32 %a, i32 %b) minsize {
; DIV32-LABEL: div32_minsize:
; DIV32-NOT: divb
%div = sdiv i32 %a, %b
ret i32 %div
}

View File

@ -1,14 +0,0 @@
; RUN: sed 's/^;.*$//' %s \
; RUN: | FileCheck --strict-whitespace --match-full-lines %s
bla1
bla2
bla3
bla4
bla5
; CHECK-LABEL:bla1
; CHECK-NEXT:bla2
; CHECK-NEXT: bla3
; CHECK-NEXT:bla4
; CHECK-NEXT: bla5

View File

@ -1,38 +0,0 @@
# RUN: llvm-mc %s -triple=mips64-unknown-linux -disassemble -mcpu=mips4 | FileCheck %s
# XFAIL: *
0x46 0x2f 0x79 0x32 # CHECK: c.eq.d $fcc1, $f15, $f15
0x46 0x11 0xc5 0x32 # CHECK: c.eq.s $fcc5, $f24, $f17
0x46 0x35 0x5c 0x30 # CHECK: c.f.d $fcc4, $f11, $f21
0x46 0x07 0xf4 0x30 # CHECK: c.f.s $fcc4, $f30, $f7
0x46 0x21 0x94 0x3e # CHECK: c.le.d $fcc4, $f18, $f1
0x46 0x04 0xc6 0x3e # CHECK: c.le.s $fcc6, $f24, $f4
0x46 0x23 0x4b 0x3c # CHECK: c.lt.d $fcc3, $f9, $f3
0x46 0x0e 0x8a 0x3c # CHECK: c.lt.s $fcc2, $f17, $f14
0x46 0x30 0xad 0x3d # CHECK: c.nge.d $fcc5, $f21, $f16
0x46 0x08 0x5b 0x3d # CHECK: c.nge.s $fcc3, $f11, $f8
0x46 0x17 0xfa 0x3b # CHECK: c.ngl.s $fcc2, $f31, $f23
0x46 0x17 0x92 0x39 # CHECK: c.ngle.s $fcc2, $f18, $f23
0x46 0x27 0xc4 0x3f # CHECK: c.ngt.d $fcc4, $f24, $f7
0x46 0x0d 0x45 0x3f # CHECK: c.ngt.s $fcc5, $f8, $f13
0x46 0x3f 0x82 0x36 # CHECK: c.ole.d $fcc2, $f16, $f31
0x46 0x14 0x3b 0x36 # CHECK: c.ole.s $fcc3, $f7, $f20
0x46 0x3c 0x9c 0x34 # CHECK: c.olt.d $fcc4, $f19, $f28
0x46 0x07 0xa6 0x34 # CHECK: c.olt.s $fcc6, $f20, $f7
0x46 0x27 0xfc 0x3a # CHECK: c.seq.d $fcc4, $f31, $f7
0x46 0x19 0x0f 0x3a # CHECK: c.seq.s $fcc7, $f1, $f25
0x46 0x39 0x6c 0x33 # CHECK: c.ueq.d $fcc4, $f13, $f25
0x46 0x1e 0x1e 0x33 # CHECK: c.ueq.s $fcc6, $f3, $f30
0x46 0x32 0xcf 0x37 # CHECK: c.ule.d $fcc7, $f25, $f18
0x46 0x1e 0xaf 0x37 # CHECK: c.ule.s $fcc7, $f21, $f30
0x46 0x31 0x36 0x35 # CHECK: c.ult.d $fcc6, $f6, $f17
0x46 0x0a 0xc7 0x35 # CHECK: c.ult.s $fcc7, $f24, $f10
0x46 0x38 0xbe 0x31 # CHECK: c.un.d $fcc6, $f23, $f24
0x46 0x04 0xf1 0x31 # CHECK: c.un.s $fcc1, $f30, $f4
0x4e 0x74 0xd4 0xa1 # CHECK: madd.d $f18, $f19, $f26, $f20
0x4f 0xf9 0x98 0x60 # CHECK: madd.s $f1, $f31, $f19, $f25
0x4c 0x32 0xfa 0xa9 # CHECK: msub.d $f10, $f1, $f31, $f18
0x4e 0x70 0x53 0x28 # CHECK: msub.s $f12, $f19, $f10, $f16
0x4d 0x33 0x74 0xb1 # CHECK: nmadd.d $f18, $f9, $f14, $f19
0x4c 0xac 0xc8 0x30 # CHECK: nmadd.s $f0, $f5, $f25, $f12
0x4d 0x1e 0x87 0xb9 # CHECK: nmsub.d $f30, $f8, $f16, $f30
0x4f 0x04 0x98 0x78 # CHECK: nmsub.s $f1, $f24, $f19, $f4

View File

@ -1,10 +0,0 @@
# Instructions that are invalid and are correctly rejected but use the wrong
# error message at the moment.
#
# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips3 \
# RUN: 2>%t1
# RUN: FileCheck %s < %t1
.set noat
bc1fl $fcc7,27 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
bc1tl $fcc7,27 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction

View File

@ -1,3 +0,0 @@
; RUN: not llvm-xray extract %S/Inputs/elf64-badentrysizes.bin 2>&1 | FileCheck %s
; CHECK: llvm-xray: Cannot extract instrumentation map from '{{.*}}elf64-badentrysizes.bin'.
; CHECK-NEXT: Instrumentation map entries not evenly divisible by size of an XRay sled entry in ELF64.

View File

@ -1,90 +0,0 @@
//===- BuiltinDumper.cpp ---------------------------------------- *- C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "BuiltinDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
using namespace llvm;
using namespace llvm::pdb;
BuiltinDumper::BuiltinDumper(LinePrinter &P)
: PDBSymDumper(false), Printer(P) {}
void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol);
}
StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
PDB_BuiltinType Type = Symbol.getBuiltinType();
switch (Type) {
case PDB_BuiltinType::Float:
if (Symbol.getLength() == 4)
return "float";
return "double";
case PDB_BuiltinType::UInt:
switch (Symbol.getLength()) {
case 8:
return "unsigned __int64";
case 4:
return "unsigned int";
case 2:
return "unsigned short";
case 1:
return "unsigned char";
default:
return "unsigned";
}
case PDB_BuiltinType::Int:
switch (Symbol.getLength()) {
case 8:
return "__int64";
case 4:
return "int";
case 2:
return "short";
case 1:
return "char";
default:
return "int";
}
case PDB_BuiltinType::Char:
return "char";
case PDB_BuiltinType::WCharT:
return "wchar_t";
case PDB_BuiltinType::Void:
return "void";
case PDB_BuiltinType::Long:
return "long";
case PDB_BuiltinType::ULong:
return "unsigned long";
case PDB_BuiltinType::Bool:
return "bool";
case PDB_BuiltinType::Currency:
return "CURRENCY";
case PDB_BuiltinType::Date:
return "DATE";
case PDB_BuiltinType::Variant:
return "VARIANT";
case PDB_BuiltinType::Complex:
return "complex";
case PDB_BuiltinType::Bitfield:
return "bitfield";
case PDB_BuiltinType::BSTR:
return "BSTR";
case PDB_BuiltinType::HResult:
return "HRESULT";
case PDB_BuiltinType::BCD:
return "HRESULT";
default:
return "void";
}
}

View File

@ -1,35 +0,0 @@
//===- BuiltinDumper.h ---------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_BUILTINDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_BUILTINDUMPER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class BuiltinDumper : public PDBSymDumper {
public:
BuiltinDumper(LinePrinter &P);
void start(const PDBSymbolTypeBuiltin &Symbol);
private:
StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol);
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,191 +0,0 @@
//===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ClassDefinitionDumper.h"
#include "EnumDumper.h"
#include "FunctionDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "TypedefDumper.h"
#include "VariableDumper.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
#include "llvm/Support/Format.h"
using namespace llvm;
using namespace llvm::pdb;
ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
std::string Name = Class.getName();
WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
if (Bases->getChildCount() > 0) {
Printer.Indent();
Printer.NewLine();
Printer << ":";
uint32_t BaseIndex = 0;
while (auto Base = Bases->getNext()) {
Printer << " ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
if (Base->isVirtualBaseClass())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
if (++BaseIndex < Bases->getChildCount()) {
Printer.NewLine();
Printer << ",";
}
}
Printer.Unindent();
}
Printer << " {";
auto Children = Class.findAllChildren();
if (Children->getChildCount() == 0) {
Printer << "}";
return;
}
// Try to dump symbols organized by member access level. Public members
// first, then protected, then private. This might be slow, so it's worth
// reconsidering the value of this if performance of large PDBs is a problem.
// NOTE: Access level of nested types is not recorded in the PDB, so we have
// a special case for them.
SymbolGroupByAccess Groups;
Groups.insert(std::make_pair(0, SymbolGroup()));
Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup()));
Groups.insert(
std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup()));
Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup()));
while (auto Child = Children->getNext()) {
PDB_MemberAccess Access = Child->getRawSymbol().getAccess();
if (isa<PDBSymbolTypeBaseClass>(*Child))
continue;
auto &AccessGroup = Groups.find((int)Access)->second;
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
continue;
if (Func->getLength() == 0 && !Func->isPureVirtual() &&
!Func->isIntroVirtualFunction())
continue;
Child.release();
AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
} else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) {
Child.release();
AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data));
} else {
AccessGroup.Unknown.push_back(std::move(Child));
}
}
int Count = 0;
Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0]);
Count += dumpAccessGroup(PDB_MemberAccess::Public,
Groups[(int)PDB_MemberAccess::Public]);
Count += dumpAccessGroup(PDB_MemberAccess::Protected,
Groups[(int)PDB_MemberAccess::Protected]);
Count += dumpAccessGroup(PDB_MemberAccess::Private,
Groups[(int)PDB_MemberAccess::Private]);
if (Count > 0)
Printer.NewLine();
Printer << "}";
}
int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access,
const SymbolGroup &Group) {
if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty())
return 0;
int Count = 0;
if (Access == PDB_MemberAccess::Private) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Keyword).get() << "private";
Printer << ":";
} else if (Access == PDB_MemberAccess::Protected) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Keyword).get() << "protected";
Printer << ":";
} else if (Access == PDB_MemberAccess::Public) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Keyword).get() << "public";
Printer << ":";
}
Printer.Indent();
for (auto iter = Group.Functions.begin(), end = Group.Functions.end();
iter != end; ++iter) {
++Count;
(*iter)->dump(*this);
}
for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end;
++iter) {
++Count;
(*iter)->dump(*this);
}
for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end();
iter != end; ++iter) {
++Count;
(*iter)->dump(*this);
}
Printer.Unindent();
return Count;
}
void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {}
void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) {
VariableDumper Dumper(Printer);
Dumper.start(Symbol);
}
void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) {
if (Printer.IsSymbolExcluded(Symbol.getName()))
return;
Printer.NewLine();
FunctionDumper Dumper(Printer);
Dumper.start(Symbol, FunctionDumper::PointerType::None);
}
void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {}
void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
Printer.NewLine();
EnumDumper Dumper(Printer);
Dumper.start(Symbol);
}
void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
Printer.NewLine();
TypedefDumper Dumper(Printer);
Dumper.start(Symbol);
}
void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {}

View File

@ -1,63 +0,0 @@
//===- ClassDefinitionDumper.h - --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include <list>
#include <memory>
#include <unordered_map>
namespace llvm {
namespace pdb {
class LinePrinter;
class ClassDefinitionDumper : public PDBSymDumper {
public:
ClassDefinitionDumper(LinePrinter &P);
void start(const PDBSymbolTypeUDT &Exe);
void dump(const PDBSymbolTypeBaseClass &Symbol) override;
void dump(const PDBSymbolData &Symbol) override;
void dump(const PDBSymbolTypeEnum &Symbol) override;
void dump(const PDBSymbolFunc &Symbol) override;
void dump(const PDBSymbolTypeTypedef &Symbol) override;
void dump(const PDBSymbolTypeUDT &Symbol) override;
void dump(const PDBSymbolTypeVTable &Symbol) override;
private:
LinePrinter &Printer;
struct SymbolGroup {
SymbolGroup() {}
SymbolGroup(SymbolGroup &&Other) {
Functions = std::move(Other.Functions);
Data = std::move(Other.Data);
Unknown = std::move(Other.Unknown);
}
std::list<std::unique_ptr<PDBSymbolFunc>> Functions;
std::list<std::unique_ptr<PDBSymbolData>> Data;
std::list<std::unique_ptr<PDBSymbol>> Unknown;
SymbolGroup(const SymbolGroup &other) = delete;
SymbolGroup &operator=(const SymbolGroup &other) = delete;
};
typedef std::unordered_map<int, SymbolGroup> SymbolGroupByAccess;
int dumpAccessGroup(PDB_MemberAccess Access, const SymbolGroup &Group);
};
}
}
#endif

View File

@ -1,195 +0,0 @@
//===- CompilandDumper.cpp - llvm-pdbdump compiland symbol dumper *- C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CompilandDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "FunctionDumper.h"
#include <utility>
using namespace llvm;
using namespace llvm::pdb;
CompilandDumper::CompilandDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {}
void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {}
void CompilandDumper::start(const PDBSymbolCompiland &Symbol,
CompilandDumpFlags opts) {
std::string FullName = Symbol.getName();
if (Printer.IsCompilandExcluded(FullName))
return;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Path).get() << FullName;
if (opts & Flags::Lines) {
const IPDBSession &Session = Symbol.getSession();
auto Files = Session.getSourceFilesForCompiland(Symbol);
Printer.Indent();
while (auto File = Files->getNext()) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName();
auto Lines = Session.findLineNumbers(Symbol, *File);
Printer.Indent();
while (auto Line = Lines->getNext()) {
Printer.NewLine();
uint32_t LineStart = Line->getLineNumber();
uint32_t LineEnd = Line->getLineNumberEnd();
Printer << "Line ";
PDB_ColorItem StatementColor = Line->isStatement()
? PDB_ColorItem::Keyword
: PDB_ColorItem::LiteralValue;
WithColor(Printer, StatementColor).get() << LineStart;
if (LineStart != LineEnd)
WithColor(Printer, StatementColor).get() << " - " << LineEnd;
uint32_t ColumnStart = Line->getColumnNumber();
uint32_t ColumnEnd = Line->getColumnNumberEnd();
if (ColumnStart != 0 || ColumnEnd != 0) {
Printer << ", Column: ";
WithColor(Printer, StatementColor).get() << ColumnStart;
if (ColumnEnd != ColumnStart)
WithColor(Printer, StatementColor).get() << " - " << ColumnEnd;
}
Printer << ", Address: ";
if (Line->getLength() > 0) {
uint64_t AddrStart = Line->getVirtualAddress();
uint64_t AddrEnd = AddrStart + Line->getLength() - 1;
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(AddrStart, 10) << " - "
<< format_hex(AddrEnd, 10) << "]";
Printer << " (" << Line->getLength() << " bytes)";
} else {
uint64_t AddrStart = Line->getVirtualAddress();
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(AddrStart, 10) << "] ";
Printer << "(0 bytes)";
}
}
Printer.Unindent();
}
Printer.Unindent();
}
if (opts & Flags::Children) {
auto ChildrenEnum = Symbol.findAllChildren();
Printer.Indent();
while (auto Child = ChildrenEnum->getNext())
Child->dump(*this);
Printer.Unindent();
}
}
void CompilandDumper::dump(const PDBSymbolData &Symbol) {
if (Printer.IsSymbolExcluded(Symbol.getName()))
return;
Printer.NewLine();
switch (auto LocType = Symbol.getLocationType()) {
case PDB_LocType::Static:
Printer << "data: ";
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]";
break;
case PDB_LocType::Constant:
Printer << "constant: ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get()
<< "[" << Symbol.getValue() << "]";
break;
default:
Printer << "data(unexpected type=" << LocType << ")";
}
Printer << " ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
}
void CompilandDumper::dump(const PDBSymbolFunc &Symbol) {
if (Symbol.getLength() == 0)
return;
if (Printer.IsSymbolExcluded(Symbol.getName()))
return;
Printer.NewLine();
FunctionDumper Dumper(Printer);
Dumper.start(Symbol, FunctionDumper::PointerType::None);
}
void CompilandDumper::dump(const PDBSymbolLabel &Symbol) {
if (Printer.IsSymbolExcluded(Symbol.getName()))
return;
Printer.NewLine();
Printer << "label ";
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
}
void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
if (Printer.IsSymbolExcluded(Symbol.getName()))
return;
Printer.NewLine();
Printer << "thunk ";
codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
uint64_t VA = Symbol.getVirtualAddress();
if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) {
uint64_t Target = Symbol.getTargetVirtualAddress();
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10);
Printer << " -> ";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10);
} else {
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(VA, 10) << " - "
<< format_hex(VA + Symbol.getLength(), 10) << "]";
}
Printer << " (";
WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
Printer << ") ";
std::string Name = Symbol.getName();
if (!Name.empty())
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
}
void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {}
void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) {
Printer.NewLine();
Printer << "unknown (" << Symbol.getSymTag() << ")";
}

View File

@ -1,44 +0,0 @@
//===- CompilandDumper.h - llvm-pdbdump compiland symbol dumper *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
typedef int CompilandDumpFlags;
class CompilandDumper : public PDBSymDumper {
public:
enum Flags { None = 0x0, Children = 0x1, Symbols = 0x2, Lines = 0x4 };
CompilandDumper(LinePrinter &P);
void start(const PDBSymbolCompiland &Symbol, CompilandDumpFlags flags);
void dump(const PDBSymbolCompilandDetails &Symbol) override;
void dump(const PDBSymbolCompilandEnv &Symbol) override;
void dump(const PDBSymbolData &Symbol) override;
void dump(const PDBSymbolFunc &Symbol) override;
void dump(const PDBSymbolLabel &Symbol) override;
void dump(const PDBSymbolThunk &Symbol) override;
void dump(const PDBSymbolTypeTypedef &Symbol) override;
void dump(const PDBSymbolUnknown &Symbol) override;
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,53 +0,0 @@
//===- EnumDumper.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "EnumDumper.h"
#include "BuiltinDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
using namespace llvm;
using namespace llvm::pdb;
EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
if (!opts::pretty::NoEnumDefs) {
auto BuiltinType = Symbol.getUnderlyingType();
if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
BuiltinType->getLength() != 4) {
Printer << " : ";
BuiltinDumper Dumper(Printer);
Dumper.start(*BuiltinType);
}
Printer << " {";
Printer.Indent();
auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
while (auto EnumValue = EnumValues->getNext()) {
if (EnumValue->getDataKind() != PDB_DataKind::Constant)
continue;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< EnumValue->getName();
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get()
<< EnumValue->getValue();
}
Printer.Unindent();
Printer.NewLine();
Printer << "}";
}
}

View File

@ -1,31 +0,0 @@
//===- EnumDumper.h - -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class EnumDumper : public PDBSymDumper {
public:
EnumDumper(LinePrinter &P);
void start(const PDBSymbolTypeEnum &Symbol);
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,41 +0,0 @@
//===- ExternalSymbolDumper.cpp -------------------------------- *- C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ExternalSymbolDumper.h"
#include "LinePrinter.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
#include "llvm/Support/Format.h"
using namespace llvm;
using namespace llvm::pdb;
ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>();
while (auto Var = Vars->getNext())
Var->dump(*this);
}
void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
std::string LinkageName = Symbol.getName();
if (Printer.IsSymbolExcluded(LinkageName))
return;
Printer.NewLine();
uint64_t Addr = Symbol.getVirtualAddress();
Printer << "[";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
Printer << "] ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
}

View File

@ -1,34 +0,0 @@
//===- ExternalSymbolDumper.h --------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class ExternalSymbolDumper : public PDBSymDumper {
public:
ExternalSymbolDumper(LinePrinter &P);
void start(const PDBSymbolExe &Symbol);
void dump(const PDBSymbolPublicSymbol &Symbol) override;
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,257 +0,0 @@
//===- FunctionDumper.cpp ------------------------------------ *- C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "FunctionDumper.h"
#include "BuiltinDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/Support/Format.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
namespace {
template <class T>
void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
FunctionDumper &Dumper) {
uint32_t ClassParentId = Symbol.getClassParentId();
auto ClassParent =
Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
ClassParentId);
if (!ClassParent)
return;
WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
Printer << "::";
}
}
FunctionDumper::FunctionDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
const char *Name, PointerType Pointer) {
auto ReturnType = Symbol.getReturnType();
ReturnType->dump(*this);
Printer << " ";
uint32_t ClassParentId = Symbol.getClassParentId();
auto ClassParent =
Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
ClassParentId);
PDB_CallingConv CC = Symbol.getCallingConvention();
bool ShouldDumpCallingConvention = true;
if ((ClassParent && CC == CallingConvention::ThisCall) ||
(!ClassParent && CC == CallingConvention::NearStdCall)) {
ShouldDumpCallingConvention = false;
}
if (Pointer == PointerType::None) {
if (ShouldDumpCallingConvention)
WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
if (ClassParent) {
Printer << "(";
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< ClassParent->getName();
Printer << "::)";
}
} else {
Printer << "(";
if (ShouldDumpCallingConvention)
WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
if (ClassParent) {
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< ClassParent->getName();
Printer << "::";
}
if (Pointer == PointerType::Reference)
Printer << "&";
else
Printer << "*";
if (Name)
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
Printer << ")";
}
Printer << "(";
if (auto ChildEnum = Symbol.getArguments()) {
uint32_t Index = 0;
while (auto Arg = ChildEnum->getNext()) {
Arg->dump(*this);
if (++Index < ChildEnum->getChildCount())
Printer << ", ";
}
}
Printer << ")";
if (Symbol.isConstType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
}
void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
uint64_t FuncStart = Symbol.getVirtualAddress();
uint64_t FuncEnd = FuncStart + Symbol.getLength();
Printer << "func [";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
}
Printer << " - ";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
}
Printer << "] (";
if (Symbol.hasFramePointer()) {
WithColor(Printer, PDB_ColorItem::Register).get()
<< Symbol.getLocalBasePointerRegisterId();
} else {
WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
}
Printer << ") ";
if (Symbol.isVirtual() || Symbol.isPureVirtual())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
auto Signature = Symbol.getSignature();
if (!Signature) {
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
if (Pointer == PointerType::Pointer)
Printer << "*";
else if (Pointer == FunctionDumper::PointerType::Reference)
Printer << "&";
return;
}
auto ReturnType = Signature->getReturnType();
ReturnType->dump(*this);
Printer << " ";
auto ClassParent = Symbol.getClassParent();
CallingConvention CC = Signature->getCallingConvention();
if (Pointer != FunctionDumper::PointerType::None)
Printer << "(";
if ((ClassParent && CC != CallingConvention::ThisCall) ||
(!ClassParent && CC != CallingConvention::NearStdCall)) {
WithColor(Printer, PDB_ColorItem::Keyword).get()
<< Signature->getCallingConvention() << " ";
}
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
if (Pointer != FunctionDumper::PointerType::None) {
if (Pointer == PointerType::Pointer)
Printer << "*";
else if (Pointer == FunctionDumper::PointerType::Reference)
Printer << "&";
Printer << ")";
}
Printer << "(";
if (auto Arguments = Symbol.getArguments()) {
uint32_t Index = 0;
while (auto Arg = Arguments->getNext()) {
auto ArgType = Arg->getType();
ArgType->dump(*this);
WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
<< Arg->getName();
if (++Index < Arguments->getChildCount())
Printer << ", ";
}
}
Printer << ")";
if (Symbol.isConstType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
if (Symbol.isPureVirtual())
Printer << " = 0";
}
void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
uint32_t ElementTypeId = Symbol.getTypeId();
auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
if (!ElementType)
return;
ElementType->dump(*this);
Printer << "[";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
Printer << "]";
}
void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
BuiltinDumper Dumper(Printer);
Dumper.start(Symbol);
}
void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
dumpClassParentWithScopeOperator(Symbol, Printer, *this);
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
// PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
// through to the real thing and dump it.
uint32_t TypeId = Symbol.getTypeId();
auto Type = Symbol.getSession().getSymbolById(TypeId);
if (!Type)
return;
Type->dump(*this);
}
void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
dumpClassParentWithScopeOperator(Symbol, Printer, *this);
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
uint32_t PointeeId = Symbol.getTypeId();
auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
if (!PointeeType)
return;
if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
FunctionDumper NestedDumper(Printer);
PointerType Pointer =
Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
NestedDumper.start(*FuncSig, nullptr, Pointer);
} else {
if (Symbol.isConstType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
PointeeType->dump(*this);
Printer << (Symbol.isReference() ? "&" : "*");
}
}
void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}

View File

@ -1,43 +0,0 @@
//===- FunctionDumper.h --------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class FunctionDumper : public PDBSymDumper {
public:
FunctionDumper(LinePrinter &P);
enum class PointerType { None, Pointer, Reference };
void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name,
PointerType Pointer);
void start(const PDBSymbolFunc &Symbol, PointerType Pointer);
void dump(const PDBSymbolTypeArray &Symbol) override;
void dump(const PDBSymbolTypeBuiltin &Symbol) override;
void dump(const PDBSymbolTypeEnum &Symbol) override;
void dump(const PDBSymbolTypeFunctionArg &Symbol) override;
void dump(const PDBSymbolTypePointer &Symbol) override;
void dump(const PDBSymbolTypeTypedef &Symbol) override;
void dump(const PDBSymbolTypeUDT &Symbol) override;
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,98 +0,0 @@
//===- TypeDumper.cpp - PDBSymDumper implementation for types *----- C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "TypeDumper.h"
#include "BuiltinDumper.h"
#include "ClassDefinitionDumper.h"
#include "EnumDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "TypedefDumper.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
using namespace llvm;
using namespace llvm::pdb;
TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void TypeDumper::start(const PDBSymbolExe &Exe) {
auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
Printer << ": (" << Enums->getChildCount() << " items)";
Printer.Indent();
while (auto Enum = Enums->getNext())
Enum->dump(*this);
Printer.Unindent();
auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>();
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
Printer << ": (" << Typedefs->getChildCount() << " items)";
Printer.Indent();
while (auto Typedef = Typedefs->getNext())
Typedef->dump(*this);
Printer.Unindent();
auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
Printer << ": (" << Classes->getChildCount() << " items)";
Printer.Indent();
while (auto Class = Classes->getNext())
Class->dump(*this);
Printer.Unindent();
}
void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
if (Symbol.getUnmodifiedTypeId() != 0)
return;
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
// Dump member enums when dumping their class definition.
if (nullptr != Symbol.getClassParent())
return;
Printer.NewLine();
EnumDumper Dumper(Printer);
Dumper.start(Symbol);
}
void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
Printer.NewLine();
TypedefDumper Dumper(Printer);
Dumper.start(Symbol);
}
void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
if (Symbol.getUnmodifiedTypeId() != 0)
return;
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
Printer.NewLine();
if (opts::pretty::NoClassDefs) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
} else {
ClassDefinitionDumper Dumper(Printer);
Dumper.start(Symbol);
}
}

View File

@ -1,34 +0,0 @@
//===- TypeDumper.h - PDBSymDumper implementation for types *- C++ ------*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class TypeDumper : public PDBSymDumper {
public:
TypeDumper(LinePrinter &P);
void start(const PDBSymbolExe &Exe);
void dump(const PDBSymbolTypeEnum &Symbol) override;
void dump(const PDBSymbolTypeTypedef &Symbol) override;
void dump(const PDBSymbolTypeUDT &Symbol) override;
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,80 +0,0 @@
//===- TypedefDumper.cpp - PDBSymDumper impl for typedefs -------- * C++ *-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "TypedefDumper.h"
#include "BuiltinDumper.h"
#include "FunctionDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
using namespace llvm;
using namespace llvm::pdb;
TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
uint32_t TargetId = Symbol.getTypeId();
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
TypeSymbol->dump(*this);
WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
<< Symbol.getName();
}
void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
BuiltinDumper Dumper(Printer);
Dumper.start(Symbol);
}
void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
}
void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
if (Symbol.isConstType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
uint32_t PointeeId = Symbol.getTypeId();
auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
if (!PointeeType)
return;
if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
if (Symbol.isReference())
Pointer = FunctionDumper::PointerType::Reference;
FunctionDumper NestedDumper(Printer);
NestedDumper.start(*FuncSig, nullptr, Pointer);
} else {
PointeeType->dump(*this);
Printer << ((Symbol.isReference()) ? "&" : "*");
}
}
void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
FunctionDumper Dumper(Printer);
Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
}
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}

View File

@ -1,39 +0,0 @@
//===- TypedefDumper.h - llvm-pdbdump typedef dumper ---------*- C++ ----*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
namespace pdb {
class LinePrinter;
class TypedefDumper : public PDBSymDumper {
public:
TypedefDumper(LinePrinter &P);
void start(const PDBSymbolTypeTypedef &Symbol);
void dump(const PDBSymbolTypeArray &Symbol) override;
void dump(const PDBSymbolTypeBuiltin &Symbol) override;
void dump(const PDBSymbolTypeEnum &Symbol) override;
void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
void dump(const PDBSymbolTypePointer &Symbol) override;
void dump(const PDBSymbolTypeUDT &Symbol) override;
private:
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,171 +0,0 @@
//===- VariableDumper.cpp - -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "VariableDumper.h"
#include "BuiltinDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "FunctionDumper.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/Support/Format.h"
using namespace llvm;
using namespace llvm::pdb;
VariableDumper::VariableDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void VariableDumper::start(const PDBSymbolData &Var) {
if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
return;
if (Printer.IsSymbolExcluded(Var.getName()))
return;
auto VarType = Var.getType();
switch (auto LocType = Var.getLocationType()) {
case PDB_LocType::Static:
Printer.NewLine();
Printer << "data [";
WithColor(Printer, PDB_ColorItem::Address).get()
<< format_hex(Var.getVirtualAddress(), 10);
Printer << "] ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::Constant:
if (isa<PDBSymbolTypeEnum>(*VarType))
break;
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
dumpSymbolTypeAndName(*VarType, Var.getName());
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
break;
case PDB_LocType::ThisRel:
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::BitField:
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
Printer << " : ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
break;
default:
Printer.NewLine();
Printer << "data ";
Printer << "unknown(" << LocType << ") ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
break;
}
}
void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
BuiltinDumper Dumper(Printer);
Dumper.start(Symbol);
}
void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {}
void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
auto PointeeType = Symbol.getPointeeType();
if (!PointeeType)
return;
if (auto Func = dyn_cast<PDBSymbolFunc>(PointeeType.get())) {
FunctionDumper NestedDumper(Printer);
FunctionDumper::PointerType Pointer =
Symbol.isReference() ? FunctionDumper::PointerType::Reference
: FunctionDumper::PointerType::Pointer;
NestedDumper.start(*Func, Pointer);
} else {
if (Symbol.isConstType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
if (Symbol.isVolatileType())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
PointeeType->dump(*this);
Printer << (Symbol.isReference() ? "&" : "*");
}
}
void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
StringRef Name) {
if (auto *ArrayType = dyn_cast<PDBSymbolTypeArray>(&Type)) {
std::string IndexSpec;
raw_string_ostream IndexStream(IndexSpec);
std::unique_ptr<PDBSymbol> ElementType = ArrayType->getElementType();
while (auto NestedArray = dyn_cast<PDBSymbolTypeArray>(ElementType.get())) {
IndexStream << "[";
IndexStream << NestedArray->getCount();
IndexStream << "]";
ElementType = NestedArray->getElementType();
}
IndexStream << "[" << ArrayType->getCount() << "]";
ElementType->dump(*this);
WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
Printer << IndexStream.str();
} else {
if (!tryDumpFunctionPointer(Type, Name)) {
Type.dump(*this);
WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
}
}
}
bool VariableDumper::tryDumpFunctionPointer(const PDBSymbol &Type,
StringRef Name) {
// Function pointers come across as pointers to function signatures. But the
// signature carries no name, so we have to handle this case separately.
if (auto *PointerType = dyn_cast<PDBSymbolTypePointer>(&Type)) {
auto PointeeType = PointerType->getPointeeType();
if (auto *FunctionSig =
dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
FunctionDumper Dumper(Printer);
FunctionDumper::PointerType PT = FunctionDumper::PointerType::Pointer;
if (PointerType->isReference())
PT = FunctionDumper::PointerType::Reference;
std::string NameStr(Name.begin(), Name.end());
Dumper.start(*FunctionSig, NameStr.c_str(), PT);
return true;
}
}
return false;
}

View File

@ -1,44 +0,0 @@
//===- VariableDumper.h - PDBSymDumper implementation for types -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
class StringRef;
namespace pdb {
class LinePrinter;
class VariableDumper : public PDBSymDumper {
public:
VariableDumper(LinePrinter &P);
void start(const PDBSymbolData &Var);
void dump(const PDBSymbolTypeBuiltin &Symbol) override;
void dump(const PDBSymbolTypeEnum &Symbol) override;
void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
void dump(const PDBSymbolTypePointer &Symbol) override;
void dump(const PDBSymbolTypeTypedef &Symbol) override;
void dump(const PDBSymbolTypeUDT &Symbol) override;
private:
void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name);
bool tryDumpFunctionPointer(const PDBSymbol &Type, StringRef Name);
LinePrinter &Printer;
};
}
}
#endif

View File

@ -1,209 +0,0 @@
//===- llvm/unittest/Analysis/LoopPassManagerTest.cpp - LPM tests ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
class TestLoopAnalysis : public AnalysisInfoMixin<TestLoopAnalysis> {
friend AnalysisInfoMixin<TestLoopAnalysis>;
static AnalysisKey Key;
int &Runs;
public:
struct Result {
Result(int Count) : BlockCount(Count) {}
int BlockCount;
};
TestLoopAnalysis(int &Runs) : Runs(Runs) {}
/// \brief Run the analysis pass over the loop and return a result.
Result run(Loop &L, LoopAnalysisManager &AM) {
++Runs;
int Count = 0;
for (auto I = L.block_begin(), E = L.block_end(); I != E; ++I)
++Count;
return Result(Count);
}
};
AnalysisKey TestLoopAnalysis::Key;
class TestLoopPass {
std::vector<StringRef> &VisitedLoops;
int &AnalyzedBlockCount;
bool OnlyUseCachedResults;
public:
TestLoopPass(std::vector<StringRef> &VisitedLoops, int &AnalyzedBlockCount,
bool OnlyUseCachedResults = false)
: VisitedLoops(VisitedLoops), AnalyzedBlockCount(AnalyzedBlockCount),
OnlyUseCachedResults(OnlyUseCachedResults) {}
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM) {
VisitedLoops.push_back(L.getName());
if (OnlyUseCachedResults) {
// Hack to force the use of the cached interface.
if (auto *AR = AM.getCachedResult<TestLoopAnalysis>(L))
AnalyzedBlockCount += AR->BlockCount;
} else {
// Typical path just runs the analysis as needed.
auto &AR = AM.getResult<TestLoopAnalysis>(L);
AnalyzedBlockCount += AR.BlockCount;
}
return PreservedAnalyses::all();
}
static StringRef name() { return "TestLoopPass"; }
};
// A test loop pass that invalidates the analysis for loops with the given name.
class TestLoopInvalidatingPass {
StringRef Name;
public:
TestLoopInvalidatingPass(StringRef LoopName) : Name(LoopName) {}
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM) {
return L.getName() == Name ? getLoopPassPreservedAnalyses()
: PreservedAnalyses::all();
}
static StringRef name() { return "TestLoopInvalidatingPass"; }
};
std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
SMDiagnostic Err;
return parseAssemblyString(IR, Err, C);
}
class LoopPassManagerTest : public ::testing::Test {
protected:
LLVMContext Context;
std::unique_ptr<Module> M;
public:
LoopPassManagerTest()
: M(parseIR(Context, "define void @f() {\n"
"entry:\n"
" br label %loop.0\n"
"loop.0:\n"
" br i1 undef, label %loop.0.0, label %end\n"
"loop.0.0:\n"
" br i1 undef, label %loop.0.0, label %loop.0.1\n"
"loop.0.1:\n"
" br i1 undef, label %loop.0.1, label %loop.0\n"
"end:\n"
" ret void\n"
"}\n"
"\n"
"define void @g() {\n"
"entry:\n"
" br label %loop.g.0\n"
"loop.g.0:\n"
" br i1 undef, label %loop.g.0, label %end\n"
"end:\n"
" ret void\n"
"}\n")) {}
};
#define EXPECT_N_ELEMENTS_EQ(N, EXPECTED, ACTUAL) \
do { \
EXPECT_EQ(N##UL, ACTUAL.size()); \
for (int I = 0; I < N; ++I) \
EXPECT_TRUE(EXPECTED[I] == ACTUAL[I]) << "Element " << I << " is " \
<< ACTUAL[I] << ". Expected " \
<< EXPECTED[I] << "."; \
} while (0)
TEST_F(LoopPassManagerTest, Basic) {
LoopAnalysisManager LAM(true);
int LoopAnalysisRuns = 0;
LAM.registerPass([&] { return TestLoopAnalysis(LoopAnalysisRuns); });
FunctionAnalysisManager FAM(true);
// We need DominatorTreeAnalysis for LoopAnalysis.
FAM.registerPass([&] { return DominatorTreeAnalysis(); });
FAM.registerPass([&] { return LoopAnalysis(); });
// We also allow loop passes to assume a set of other analyses and so need
// those.
FAM.registerPass([&] { return AAManager(); });
FAM.registerPass([&] { return TargetLibraryAnalysis(); });
FAM.registerPass([&] { return ScalarEvolutionAnalysis(); });
FAM.registerPass([&] { return AssumptionAnalysis(); });
FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });
LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });
ModuleAnalysisManager MAM(true);
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
ModulePassManager MPM(true);
FunctionPassManager FPM(true);
// Visit all of the loops.
std::vector<StringRef> VisitedLoops1;
int AnalyzedBlockCount1 = 0;
{
LoopPassManager LPM;
LPM.addPass(TestLoopPass(VisitedLoops1, AnalyzedBlockCount1));
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM)));
}
// Only use cached analyses.
std::vector<StringRef> VisitedLoops2;
int AnalyzedBlockCount2 = 0;
{
LoopPassManager LPM;
LPM.addPass(TestLoopInvalidatingPass("loop.g.0"));
LPM.addPass(TestLoopPass(VisitedLoops2, AnalyzedBlockCount2,
/*OnlyUseCachedResults=*/true));
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM)));
}
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
MPM.run(*M, MAM);
StringRef ExpectedLoops[] = {"loop.0.0", "loop.0.1", "loop.0", "loop.g.0"};
// Validate the counters and order of loops visited.
// loop.0 has 3 blocks whereas loop.0.0, loop.0.1, and loop.g.0 each have 1.
EXPECT_N_ELEMENTS_EQ(4, ExpectedLoops, VisitedLoops1);
EXPECT_EQ(6, AnalyzedBlockCount1);
EXPECT_N_ELEMENTS_EQ(4, ExpectedLoops, VisitedLoops2);
// The block from loop.g.0 won't be counted, since it wasn't cached.
EXPECT_EQ(5, AnalyzedBlockCount2);
// The first LPM runs the loop analysis for all four loops, the second uses
// cached results for everything.
EXPECT_EQ(4, LoopAnalysisRuns);
}
}