Vendor import of llvm trunk r304460:

https://llvm.org/svn/llvm-project/llvm/trunk@304460
This commit is contained in:
Dimitry Andric 2017-06-01 20:58:36 +00:00
parent ee2f195dd3
commit f382538d47
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm/dist/; revision=319461
svn path=/vendor/llvm/llvm-trunk-r304460/; revision=319462; tag=vendor/llvm/llvm-trunk-r304460
378 changed files with 12500 additions and 9924 deletions

View File

@ -44,12 +44,12 @@ Users can control the vectorization SIMD width using the command line flag "-for
$ clang -mllvm -force-vector-width=8 ...
$ opt -loop-vectorize -force-vector-width=8 ...
Users can control the unroll factor using the command line flag "-force-vector-unroll"
Users can control the unroll factor using the command line flag "-force-vector-interleave"
.. code-block:: console
$ clang -mllvm -force-vector-unroll=2 ...
$ opt -loop-vectorize -force-vector-unroll=2 ...
$ clang -mllvm -force-vector-interleave=2 ...
$ opt -loop-vectorize -force-vector-interleave=2 ...
Pragma loop hint directives
^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -454,6 +454,9 @@ class TargetTransformInfo {
/// \brief Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
/// \brief Enable inline expansion of memcmp
bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) const;
/// \brief Enable matching of interleaved access groups.
bool enableInterleavedAccessVectorization() const;
@ -828,6 +831,7 @@ class TargetTransformInfo::Concept {
unsigned VF) = 0;
virtual bool supportsEfficientVectorElementLoadStore() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
virtual bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
virtual bool allowsMisalignedMemoryAccesses(LLVMContext &Context,
@ -1047,6 +1051,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
bool enableAggressiveInterleaving(bool LoopHasReductions) override {
return Impl.enableAggressiveInterleaving(LoopHasReductions);
}
bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) override {
return Impl.expandMemCmp(I, MaxLoadSize);
}
bool enableInterleavedAccessVectorization() override {
return Impl.enableInterleavedAccessVectorization();
}

View File

@ -274,6 +274,8 @@ class TargetTransformInfoImplBase {
bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) { return false; }
bool enableInterleavedAccessVectorization() { return false; }
bool isFPVectorizationPotentiallyUnsafe() { return false; }

View File

@ -85,6 +85,8 @@ template <typename T> class ArrayRef;
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI);
/// Return true if the given value is known to be non-zero when defined. For
/// vectors, return true if every element is known to be non-zero when
/// defined. For pointers, if the context instruction and dominator tree are

View File

@ -396,7 +396,7 @@ class RegisterBankInfo {
mutable DenseMap<unsigned, std::unique_ptr<const InstructionMapping>>
MapOfInstructionMappings;
/// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
/// Create a RegisterBankInfo that can accommodate up to \p NumRegBanks
/// RegisterBank instances.
RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks);

View File

@ -410,12 +410,22 @@ namespace ISD {
/// then the result type must also be a vector type.
SETCC,
/// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but
/// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, and
/// op #2 is a *carry value*. This operator checks the result of
/// "LHS - RHS - Carry", and can be used to compare two wide integers:
/// (setcce lhshi rhshi (subc lhslo rhslo) cc). Only valid for integers.
/// FIXME: This node is deprecated in favor of SETCCCARRY.
/// It is kept around for now to provide a smooth transition path
/// toward the use of SETCCCARRY and will eventually be removed.
SETCCE,
/// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but
/// op #2 is a boolean indicating if there is an incoming carry. This
/// operator checks the result of "LHS - RHS - Carry", and can be used to
/// compare two wide integers: (setcce lhshi rhshi (subc lhslo rhslo) cc).
/// Only valid for integers.
SETCCCARRY,
/// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
/// integer shift operations. The operation ordering is:
/// [Lo,Hi] = op [LoLHS,HiLHS], Amt

View File

@ -381,7 +381,6 @@ struct MachineFunction {
StringRef Name;
unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
bool NoVRegs;
// GISel MachineFunctionProperties.
bool Legalized = false;
bool RegBankSelected = false;
@ -406,7 +405,6 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapRequired("name", MF.Name);
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
YamlIO.mapOptional("noVRegs", MF.NoVRegs);
YamlIO.mapOptional("legalized", MF.Legalized);
YamlIO.mapOptional("regBankSelected", MF.RegBankSelected);
YamlIO.mapOptional("selected", MF.Selected);

View File

@ -335,6 +335,9 @@ class MachineBasicBlock
return make_range(livein_begin(), livein_end());
}
/// Remove entry from the livein set and return iterator to the next.
livein_iterator removeLiveIn(livein_iterator I);
/// Get the clobber mask for the start of this basic block. Funclets use this
/// to prevent register allocation across funclet transitions.
const uint32_t *getBeginClobberMask(const TargetRegisterInfo *TRI) const;

View File

@ -1,4 +1,4 @@
//===-- CodeGen/MachineConstantPool.h - Abstract Constant Pool --*- C++ -*-===//
//===- CodeGen/MachineConstantPool.h - Abstract Constant Pool ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -18,29 +18,28 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/MC/SectionKind.h"
#include <cassert>
#include <climits>
#include <vector>
namespace llvm {
class Constant;
class FoldingSetNodeID;
class DataLayout;
class TargetMachine;
class Type;
class FoldingSetNodeID;
class MachineConstantPool;
class raw_ostream;
class Type;
/// Abstract base class for all machine specific constantpool value subclasses.
///
class MachineConstantPoolValue {
virtual void anchor();
Type *Ty;
public:
explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {}
virtual ~MachineConstantPoolValue() {}
virtual ~MachineConstantPoolValue() = default;
/// getType - get type of this MachineConstantPoolValue.
///
@ -81,6 +80,7 @@ class MachineConstantPoolEntry {
: Alignment(A) {
Val.ConstVal = V;
}
MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned A)
: Alignment(A) {
Val.MachineCPVal = V;
@ -153,13 +153,12 @@ class MachineConstantPool {
/// print - Used by the MachineFunction printer to print information about
/// constant pool objects. Implemented in MachineFunction.cpp
///
void print(raw_ostream &OS) const;
/// dump - Call print(cerr) to be called from the debugger.
void dump() const;
};
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINECONSTANTPOOL_H

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/MachineFunction.h --------------------------*- C++ -*-===//
//===- llvm/CodeGen/MachineFunction.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -18,38 +18,61 @@
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
#define LLVM_CODEGEN_MACHINEFUNCTION_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Recycler.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
namespace llvm {
class Value;
class BasicBlock;
class BlockAddress;
class DataLayout;
class DIExpression;
class DILocalVariable;
class DILocation;
class Function;
class GCModuleInfo;
class MachineRegisterInfo;
class MachineFrameInfo;
class GlobalValue;
class MachineConstantPool;
class MachineFrameInfo;
class MachineFunction;
class MachineJumpTableInfo;
class MachineModuleInfo;
class MachineRegisterInfo;
class MCContext;
class MCInstrDesc;
class Pass;
class PseudoSourceValueManager;
class raw_ostream;
class SlotIndexes;
class TargetMachine;
class TargetSubtargetInfo;
class TargetRegisterClass;
struct MachinePointerInfo;
class TargetSubtargetInfo;
struct WinEHFuncInfo;
template <> struct ilist_alloc_traits<MachineBasicBlock> {
@ -137,27 +160,33 @@ class MachineFunctionProperties {
bool hasProperty(Property P) const {
return Properties[static_cast<unsigned>(P)];
}
MachineFunctionProperties &set(Property P) {
Properties.set(static_cast<unsigned>(P));
return *this;
}
MachineFunctionProperties &reset(Property P) {
Properties.reset(static_cast<unsigned>(P));
return *this;
}
/// Reset all the properties.
MachineFunctionProperties &reset() {
Properties.reset();
return *this;
}
MachineFunctionProperties &set(const MachineFunctionProperties &MFP) {
Properties |= MFP.Properties;
return *this;
}
MachineFunctionProperties &reset(const MachineFunctionProperties &MFP) {
Properties.reset(MFP.Properties);
return *this;
}
// Returns true if all properties set in V (i.e. required by a pass) are set
// in this.
bool verifyRequiredProperties(const MachineFunctionProperties &V) const {
@ -180,18 +209,17 @@ struct SEHHandler {
const BlockAddress *RecoverBA;
};
/// This structure is used to retain landing pad info for the current function.
struct LandingPadInfo {
MachineBasicBlock *LandingPadBlock; // Landing pad block.
SmallVector<MCSymbol *, 1> BeginLabels; // Labels prior to invoke.
SmallVector<MCSymbol *, 1> EndLabels; // Labels after invoke.
SmallVector<SEHHandler, 1> SEHHandlers; // SEH handlers active at this lpad.
MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
std::vector<int> TypeIds; // List of type ids (filters negative).
MCSymbol *LandingPadLabel = nullptr; // Label at beginning of landing pad.
std::vector<int> TypeIds; // List of type ids (filters negative).
explicit LandingPadInfo(MachineBasicBlock *MBB)
: LandingPadBlock(MBB), LandingPadLabel(nullptr) {}
: LandingPadBlock(MBB) {}
};
class MachineFunction {
@ -239,7 +267,7 @@ class MachineFunction {
Recycler<MachineBasicBlock> BasicBlockRecycler;
// List of machine basic blocks in function
typedef ilist<MachineBasicBlock> BasicBlockListType;
using BasicBlockListType = ilist<MachineBasicBlock>;
BasicBlockListType BasicBlocks;
/// FunctionNumber - This provides a unique ID for each function emitted in
@ -281,7 +309,7 @@ class MachineFunction {
std::vector<LandingPadInfo> LandingPads;
/// Map a landing pad's EH symbol to the call site indexes.
DenseMap<MCSymbol*, SmallVector<unsigned, 4> > LPadToCallSiteMap;
DenseMap<MCSymbol*, SmallVector<unsigned, 4>> LPadToCallSiteMap;
/// Map of invoke call site index values to associated begin EH_LABEL.
DenseMap<MCSymbol*, unsigned> CallSiteMap;
@ -303,9 +331,6 @@ class MachineFunction {
/// \}
MachineFunction(const MachineFunction &) = delete;
void operator=(const MachineFunction&) = delete;
/// Clear all the members of this MachineFunction, but the ones used
/// to initialize again the MachineFunction.
/// More specifically, this deallocates all the dynamically allocated
@ -316,8 +341,8 @@ class MachineFunction {
/// In particular, the XXXInfo data structure.
/// \pre Fn, Target, MMI, and FunctionNumber are properly set.
void init();
public:
public:
struct VariableDbgInfo {
const DILocalVariable *Var;
const DIExpression *Expr;
@ -328,11 +353,13 @@ class MachineFunction {
unsigned Slot, const DILocation *Loc)
: Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy;
using VariableDbgInfoMapTy = SmallVector<VariableDbgInfo, 4>;
VariableDbgInfoMapTy VariableDbgInfos;
MachineFunction(const Function *Fn, const TargetMachine &TM,
unsigned FunctionNum, MachineModuleInfo &MMI);
MachineFunction(const MachineFunction &) = delete;
MachineFunction &operator=(const MachineFunction &) = delete;
~MachineFunction();
/// Reset the instance as if it was just created.
@ -350,19 +377,15 @@ class MachineFunction {
const DataLayout &getDataLayout() const;
/// getFunction - Return the LLVM function that this machine code represents
///
const Function *getFunction() const { return Fn; }
/// getName - Return the name of the corresponding LLVM function.
///
StringRef getName() const;
/// getFunctionNumber - Return a unique ID for the current function.
///
unsigned getFunctionNumber() const { return FunctionNumber; }
/// getTarget - Return the target machine this machine code is compiled with
///
const TargetMachine &getTarget() const { return Target; }
/// getSubtarget - Return the subtarget for which this machine code is being
@ -378,14 +401,12 @@ class MachineFunction {
}
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
const MachineRegisterInfo &getRegInfo() const { return *RegInfo; }
/// getFrameInfo - Return the frame info object for the current function.
/// This object contains information about objects allocated on the stack
/// frame of the current function in an abstract way.
///
MachineFrameInfo &getFrameInfo() { return *FrameInfo; }
const MachineFrameInfo &getFrameInfo() const { return *FrameInfo; }
@ -402,7 +423,6 @@ class MachineFunction {
/// getConstantPool - Return the constant pool object for the current
/// function.
///
MachineConstantPool *getConstantPool() { return ConstantPool; }
const MachineConstantPool *getConstantPool() const { return ConstantPool; }
@ -413,11 +433,9 @@ class MachineFunction {
WinEHFuncInfo *getWinEHFuncInfo() { return WinEHInfo; }
/// getAlignment - Return the alignment (log2, not bytes) of the function.
///
unsigned getAlignment() const { return Alignment; }
/// setAlignment - Set the alignment (log2, not bytes) of the function.
///
void setAlignment(unsigned A) { Alignment = A; }
/// ensureAlignment - Make sure the function is at least 1 << A bytes aligned.
@ -487,7 +505,6 @@ class MachineFunction {
bool shouldSplitStack() const;
/// getNumBlockIDs - Return the number of MBB ID's allocated.
///
unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); }
/// RenumberBlocks - This discards all of the MachineBasicBlock numbers and
@ -499,7 +516,6 @@ class MachineFunction {
/// print - Print out the MachineFunction in a format suitable for debugging
/// to the specified stream.
///
void print(raw_ostream &OS, const SlotIndexes* = nullptr) const;
/// viewCFG - This function is meant for use from the debugger. You can just
@ -507,7 +523,6 @@ class MachineFunction {
/// program, displaying the CFG of the current function with the code for each
/// basic block inside. This depends on there being a 'dot' and 'gv' program
/// in your path.
///
void viewCFG() const;
/// viewCFGOnly - This function is meant for use from the debugger. It works
@ -518,7 +533,6 @@ class MachineFunction {
void viewCFGOnly() const;
/// dump - Print the current MachineFunction to cerr, useful for debugger use.
///
void dump() const;
/// Run the current MachineFunction through the machine code verifier, useful
@ -528,10 +542,10 @@ class MachineFunction {
bool AbortOnError = true) const;
// Provide accessors for the MachineBasicBlock list...
typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator;
typedef BasicBlockListType::const_reverse_iterator const_reverse_iterator;
typedef BasicBlockListType::reverse_iterator reverse_iterator;
using iterator = BasicBlockListType::iterator;
using const_iterator = BasicBlockListType::const_iterator;
using const_reverse_iterator = BasicBlockListType::const_reverse_iterator;
using reverse_iterator = BasicBlockListType::reverse_iterator;
/// Support for MachineBasicBlock::getNextNode().
static BasicBlockListType MachineFunction::*
@ -590,11 +604,9 @@ class MachineFunction {
//===--------------------------------------------------------------------===//
// Internal functions used to automatically number MachineBasicBlocks
//
/// \brief Adds the MBB to the internal numbering. Returns the unique number
/// assigned to the MBB.
///
unsigned addToMBBNumbering(MachineBasicBlock *MBB) {
MBBNumbering.push_back(MBB);
return (unsigned)MBBNumbering.size()-1;
@ -610,7 +622,6 @@ class MachineFunction {
/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead
/// of `new MachineInstr'.
///
MachineInstr *CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL,
bool NoImp = false);
@ -623,16 +634,13 @@ class MachineFunction {
MachineInstr *CloneMachineInstr(const MachineInstr *Orig);
/// DeleteMachineInstr - Delete the given MachineInstr.
///
void DeleteMachineInstr(MachineInstr *MI);
/// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this
/// instead of `new MachineBasicBlock'.
///
MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = nullptr);
/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
///
void DeleteMachineBasicBlock(MachineBasicBlock *MBB);
/// getMachineMemOperand - Allocate a new MachineMemOperand.
@ -653,7 +661,7 @@ class MachineFunction {
MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO,
int64_t Offset, uint64_t Size);
typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity;
/// Allocate an array of MachineOperands. This is only intended for use by
/// internal MachineInstr functions.
@ -700,7 +708,6 @@ class MachineFunction {
//===--------------------------------------------------------------------===//
// Label Manipulation.
//
/// getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
/// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a
@ -858,13 +865,16 @@ template <> struct GraphTraits<MachineFunction*> :
static NodeRef getEntryNode(MachineFunction *F) { return &F->front(); }
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
typedef pointer_iterator<MachineFunction::iterator> nodes_iterator;
using nodes_iterator = pointer_iterator<MachineFunction::iterator>;
static nodes_iterator nodes_begin(MachineFunction *F) {
return nodes_iterator(F->begin());
}
static nodes_iterator nodes_end(MachineFunction *F) {
return nodes_iterator(F->end());
}
static unsigned size (MachineFunction *F) { return F->size(); }
};
template <> struct GraphTraits<const MachineFunction*> :
@ -872,37 +882,39 @@ template <> struct GraphTraits<const MachineFunction*> :
static NodeRef getEntryNode(const MachineFunction *F) { return &F->front(); }
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
typedef pointer_iterator<MachineFunction::const_iterator> nodes_iterator;
using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
static nodes_iterator nodes_begin(const MachineFunction *F) {
return nodes_iterator(F->begin());
}
static nodes_iterator nodes_end (const MachineFunction *F) {
return nodes_iterator(F->end());
}
static unsigned size (const MachineFunction *F) {
return F->size();
}
};
// Provide specializations of GraphTraits to be able to treat a function as a
// graph of basic blocks... and to walk it in inverse order. Inverse order for
// a function is considered to be when traversing the predecessor edges of a BB
// instead of the successor edges.
//
template <> struct GraphTraits<Inverse<MachineFunction*> > :
public GraphTraits<Inverse<MachineBasicBlock*> > {
template <> struct GraphTraits<Inverse<MachineFunction*>> :
public GraphTraits<Inverse<MachineBasicBlock*>> {
static NodeRef getEntryNode(Inverse<MachineFunction *> G) {
return &G.Graph->front();
}
};
template <> struct GraphTraits<Inverse<const MachineFunction*> > :
public GraphTraits<Inverse<const MachineBasicBlock*> > {
template <> struct GraphTraits<Inverse<const MachineFunction*>> :
public GraphTraits<Inverse<const MachineBasicBlock*>> {
static NodeRef getEntryNode(Inverse<const MachineFunction *> G) {
return &G.Graph->front();
}
};
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEFUNCTION_H

View File

@ -1,4 +1,4 @@
//===- MachineFunctionInitializer.h - machine function initializer ---------===//
//=- MachineFunctionInitializer.h - machine function initializer --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@ -25,7 +25,7 @@ class MachineFunctionInitializer {
virtual void anchor();
public:
virtual ~MachineFunctionInitializer() {}
virtual ~MachineFunctionInitializer() = default;
/// Initialize the machine function.
///
@ -35,4 +35,4 @@ class MachineFunctionInitializer {
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===//
//===- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -17,7 +17,6 @@
#define LLVM_CODEGEN_MACHINEINSTR_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
@ -28,19 +27,27 @@
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Target/TargetOpcodes.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <utility>
namespace llvm {
class StringRef;
template <typename T> class ArrayRef;
template <typename T> class SmallVectorImpl;
class DILocalVariable;
class DIExpression;
class DILocalVariable;
class MachineBasicBlock;
class MachineFunction;
class MachineMemOperand;
class MachineRegisterInfo;
class ModuleSlotTracker;
class raw_ostream;
template <typename T> class SmallVectorImpl;
class StringRef;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
class MachineFunction;
class MachineMemOperand;
//===----------------------------------------------------------------------===//
/// Representation of each machine instruction.
@ -53,7 +60,7 @@ class MachineInstr
: public ilist_node_with_parent<MachineInstr, MachineBasicBlock,
ilist_sentinel_tracking<true>> {
public:
typedef MachineMemOperand **mmo_iterator;
using mmo_iterator = MachineMemOperand **;
/// Flags to specify different kinds of comments to output in
/// assembly code. These flags carry semantic information not
@ -72,43 +79,39 @@ class MachineInstr
BundledPred = 1 << 2, // Instruction has bundled predecessors.
BundledSucc = 1 << 3 // Instruction has bundled successors.
};
private:
const MCInstrDesc *MCID; // Instruction descriptor.
MachineBasicBlock *Parent; // Pointer to the owning basic block.
MachineBasicBlock *Parent = nullptr; // Pointer to the owning basic block.
// Operands are allocated by an ArrayRecycler.
MachineOperand *Operands; // Pointer to the first operand.
unsigned NumOperands; // Number of operands on instruction.
typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
MachineOperand *Operands = nullptr; // Pointer to the first operand.
unsigned NumOperands = 0; // Number of operands on instruction.
using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity;
OperandCapacity CapOperands; // Capacity of the Operands array.
uint8_t Flags; // Various bits of additional
uint8_t Flags = 0; // Various bits of additional
// information about machine
// instruction.
uint8_t AsmPrinterFlags; // Various bits of information used by
uint8_t AsmPrinterFlags = 0; // Various bits of information used by
// the AsmPrinter to emit helpful
// comments. This is *not* semantic
// information. Do not use this for
// anything other than to convey comment
// information to AsmPrinter.
uint8_t NumMemRefs; // Information on memory references.
uint8_t NumMemRefs = 0; // Information on memory references.
// Note that MemRefs == nullptr, means 'don't know', not 'no memory access'.
// Calling code must treat missing information conservatively. If the number
// of memory operands required to be precise exceeds the maximum value of
// NumMemRefs - currently 256 - we remove the operands entirely. Note also
// that this is a non-owning reference to a shared copy on write buffer owned
// by the MachineFunction and created via MF.allocateMemRefsArray.
mmo_iterator MemRefs;
mmo_iterator MemRefs = nullptr;
DebugLoc debugLoc; // Source line information.
MachineInstr(const MachineInstr&) = delete;
void operator=(const MachineInstr&) = delete;
// Use MachineFunction::DeleteMachineInstr() instead.
~MachineInstr() = delete;
// Intrusive list support
friend struct ilist_traits<MachineInstr>;
friend struct ilist_callback_traits<MachineBasicBlock>;
@ -128,6 +131,11 @@ class MachineInstr
friend class MachineFunction;
public:
MachineInstr(const MachineInstr &) = delete;
MachineInstr &operator=(const MachineInstr &) = delete;
// Use MachineFunction::DeleteMachineInstr() instead.
~MachineInstr() = delete;
const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; }
@ -178,7 +186,6 @@ class MachineInstr
Flags &= ~((uint8_t)Flag);
}
/// Return true if MI is in a bundle (but not the first MI in a bundle).
///
/// A bundle looks like this before it's finalized:
@ -263,7 +270,6 @@ class MachineInstr
/// earlier.
///
/// If this method returns, the caller should try to recover from the error.
///
void emitError(StringRef Msg) const;
/// Returns the target instruction descriptor of this MachineInstr.
@ -273,7 +279,6 @@ class MachineInstr
unsigned getOpcode() const { return MCID->Opcode; }
/// Access to explicit operands of the instruction.
///
unsigned getNumOperands() const { return NumOperands; }
const MachineOperand& getOperand(unsigned i) const {
@ -289,8 +294,8 @@ class MachineInstr
unsigned getNumExplicitOperands() const;
/// iterator/begin/end - Iterate over all operands of a machine instruction.
typedef MachineOperand *mop_iterator;
typedef const MachineOperand *const_mop_iterator;
using mop_iterator = MachineOperand *;
using const_mop_iterator = const MachineOperand *;
mop_iterator operands_begin() { return Operands; }
mop_iterator operands_end() { return Operands + NumOperands; }
@ -713,7 +718,6 @@ class MachineInstr
return hasProperty(MCID::ExtraDefRegAllocReq, Type);
}
enum MICheckType {
CheckDefs, // Check all operands for equality
CheckKillDead, // Check all operands including kill / dead markers
@ -767,6 +771,7 @@ class MachineInstr
/// Returns true if the MachineInstr represents a label.
bool isLabel() const { return isEHLabel() || isGCLabel(); }
bool isCFIInstruction() const {
return getOpcode() == TargetOpcode::CFI_INSTRUCTION;
}
@ -775,6 +780,7 @@ class MachineInstr
bool isPosition() const { return isLabel() || isCFIInstruction(); }
bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; }
/// A DBG_VALUE is indirect iff the first operand is a register and
/// the second operand is an immediate.
bool isIndirectDebugValue() const {
@ -787,29 +793,38 @@ class MachineInstr
bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
bool isMSInlineAsm() const {
return getOpcode() == TargetOpcode::INLINEASM && getInlineAsmDialect();
}
bool isStackAligningInlineAsm() const;
InlineAsm::AsmDialect getInlineAsmDialect() const;
bool isInsertSubreg() const {
return getOpcode() == TargetOpcode::INSERT_SUBREG;
}
bool isSubregToReg() const {
return getOpcode() == TargetOpcode::SUBREG_TO_REG;
}
bool isRegSequence() const {
return getOpcode() == TargetOpcode::REG_SEQUENCE;
}
bool isBundle() const {
return getOpcode() == TargetOpcode::BUNDLE;
}
bool isCopy() const {
return getOpcode() == TargetOpcode::COPY;
}
bool isFullCopy() const {
return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg();
}
bool isExtractSubreg() const {
return getOpcode() == TargetOpcode::EXTRACT_SUBREG;
}
@ -978,7 +993,6 @@ class MachineInstr
///
/// The flag operand is an immediate that can be decoded with methods like
/// InlineAsm::hasRegClassConstraint().
///
int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const;
/// Compute the static register class constraint for operand OpIdx.
@ -987,7 +1001,6 @@ class MachineInstr
///
/// Returns NULL if the static register class constraint cannot be
/// determined.
///
const TargetRegisterClass*
getRegClassConstraint(unsigned OpIdx,
const TargetInstrInfo *TII,
@ -1328,6 +1341,6 @@ inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) {
return OS;
}
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEINSTR_H

View File

@ -15,34 +15,37 @@
#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/simple_ilist.h"
#include <cassert>
#include <iterator>
#include <type_traits>
namespace llvm {
template <class T, bool IsReverse> struct MachineInstrBundleIteratorTraits;
template <class T> struct MachineInstrBundleIteratorTraits<T, false> {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::iterator instr_iterator;
typedef typename list_type::iterator nonconst_instr_iterator;
typedef typename list_type::const_iterator const_instr_iterator;
using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
using instr_iterator = typename list_type::iterator;
using nonconst_instr_iterator = typename list_type::iterator;
using const_instr_iterator = typename list_type::const_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<T, true> {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::reverse_iterator instr_iterator;
typedef typename list_type::reverse_iterator nonconst_instr_iterator;
typedef typename list_type::const_reverse_iterator const_instr_iterator;
using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
using instr_iterator = typename list_type::reverse_iterator;
using nonconst_instr_iterator = typename list_type::reverse_iterator;
using const_instr_iterator = typename list_type::const_reverse_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<const T, false> {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::const_iterator instr_iterator;
typedef typename list_type::iterator nonconst_instr_iterator;
typedef typename list_type::const_iterator const_instr_iterator;
using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
using instr_iterator = typename list_type::const_iterator;
using nonconst_instr_iterator = typename list_type::iterator;
using const_instr_iterator = typename list_type::const_iterator;
};
template <class T> struct MachineInstrBundleIteratorTraits<const T, true> {
typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
typedef typename list_type::const_reverse_iterator instr_iterator;
typedef typename list_type::reverse_iterator nonconst_instr_iterator;
typedef typename list_type::const_reverse_iterator const_instr_iterator;
using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>;
using instr_iterator = typename list_type::const_reverse_iterator;
using nonconst_instr_iterator = typename list_type::reverse_iterator;
using const_instr_iterator = typename list_type::const_reverse_iterator;
};
template <bool IsReverse> struct MachineInstrBundleIteratorHelper;
@ -104,27 +107,27 @@ template <> struct MachineInstrBundleIteratorHelper<true> {
/// inside bundles (i.e. walk top level MIs only).
template <typename Ty, bool IsReverse = false>
class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
typedef MachineInstrBundleIteratorTraits<Ty, IsReverse> Traits;
typedef typename Traits::instr_iterator instr_iterator;
using Traits = MachineInstrBundleIteratorTraits<Ty, IsReverse>;
using instr_iterator = typename Traits::instr_iterator;
instr_iterator MII;
public:
typedef typename instr_iterator::value_type value_type;
typedef typename instr_iterator::difference_type difference_type;
typedef typename instr_iterator::pointer pointer;
typedef typename instr_iterator::reference reference;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename instr_iterator::const_pointer const_pointer;
typedef typename instr_iterator::const_reference const_reference;
using value_type = typename instr_iterator::value_type;
using difference_type = typename instr_iterator::difference_type;
using pointer = typename instr_iterator::pointer;
using reference = typename instr_iterator::reference;
using const_pointer = typename instr_iterator::const_pointer;
using const_reference = typename instr_iterator::const_reference;
using iterator_category = std::bidirectional_iterator_tag;
private:
typedef typename Traits::nonconst_instr_iterator nonconst_instr_iterator;
typedef typename Traits::const_instr_iterator const_instr_iterator;
typedef MachineInstrBundleIterator<
typename nonconst_instr_iterator::value_type, IsReverse>
nonconst_iterator;
typedef MachineInstrBundleIterator<Ty, !IsReverse> reverse_iterator;
using nonconst_instr_iterator = typename Traits::nonconst_instr_iterator;
using const_instr_iterator = typename Traits::const_instr_iterator;
using nonconst_iterator =
MachineInstrBundleIterator<typename nonconst_instr_iterator::value_type,
IsReverse>;
using reverse_iterator = MachineInstrBundleIterator<Ty, !IsReverse>;
public:
MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {
@ -138,12 +141,14 @@ class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
"MachineInstrBundleIterator with a "
"bundled MI");
}
MachineInstrBundleIterator(pointer MI) : MII(MI) {
// FIXME: This conversion should be explicit.
assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
"MachineInstrBundleIterator "
"with a bundled MI");
}
// Template allows conversion from const to nonconst.
template <class OtherTy>
MachineInstrBundleIterator(
@ -151,6 +156,7 @@ class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
void *>::type = nullptr)
: MII(I.getInstrIterator()) {}
MachineInstrBundleIterator() : MII(nullptr) {}
/// Explicit conversion between forward/reverse iterators.
@ -280,4 +286,4 @@ class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H

View File

@ -33,6 +33,8 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
namespace llvm {
@ -71,6 +73,7 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
private:
friend class LoopInfoBase<MachineBasicBlock, MachineLoop>;
explicit MachineLoop(MachineBasicBlock *MBB)
: LoopBase<MachineBasicBlock, MachineLoop>(MBB) {}
};
@ -79,11 +82,9 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
extern template class LoopInfoBase<MachineBasicBlock, MachineLoop>;
class MachineLoopInfo : public MachineFunctionPass {
LoopInfoBase<MachineBasicBlock, MachineLoop> LI;
friend class LoopBase<MachineBasicBlock, MachineLoop>;
void operator=(const MachineLoopInfo &) = delete;
MachineLoopInfo(const MachineLoopInfo &) = delete;
LoopInfoBase<MachineBasicBlock, MachineLoop> LI;
public:
static char ID; // Pass identification, replacement for typeid
@ -91,6 +92,8 @@ class MachineLoopInfo : public MachineFunctionPass {
MachineLoopInfo() : MachineFunctionPass(ID) {
initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
}
MachineLoopInfo(const MachineLoopInfo &) = delete;
MachineLoopInfo &operator=(const MachineLoopInfo &) = delete;
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
@ -103,7 +106,7 @@ class MachineLoopInfo : public MachineFunctionPass {
bool SpeculativePreheader = false) const;
/// The iterator interface to the top-level loops in the current function.
typedef LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator iterator;
using iterator = LoopInfoBase<MachineBasicBlock, MachineLoop>::iterator;
inline iterator begin() const { return LI.begin(); }
inline iterator end() const { return LI.end(); }
bool empty() const { return LI.empty(); }
@ -166,11 +169,10 @@ class MachineLoopInfo : public MachineFunctionPass {
}
};
// Allow clients to walk the list of nested loops...
template <> struct GraphTraits<const MachineLoop*> {
typedef const MachineLoop *NodeRef;
typedef MachineLoopInfo::iterator ChildIteratorType;
using NodeRef = const MachineLoop *;
using ChildIteratorType = MachineLoopInfo::iterator;
static NodeRef getEntryNode(const MachineLoop *L) { return L; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
@ -178,14 +180,14 @@ template <> struct GraphTraits<const MachineLoop*> {
};
template <> struct GraphTraits<MachineLoop*> {
typedef MachineLoop *NodeRef;
typedef MachineLoopInfo::iterator ChildIteratorType;
using NodeRef = MachineLoop *;
using ChildIteratorType = MachineLoopInfo::iterator;
static NodeRef getEntryNode(MachineLoop *L) { return L; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
};
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINELOOPINFO_H

View File

@ -31,35 +31,26 @@
#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H
#define LLVM_CODEGEN_MACHINEMODULEINFO_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
#include <memory>
#include <utility>
#include <vector>
namespace llvm {
//===----------------------------------------------------------------------===//
// Forward declarations.
class BlockAddress;
class BasicBlock;
class CallInst;
class Constant;
class GlobalVariable;
class LandingPadInst;
class MDNode;
class MMIAddrLabelMap;
class MachineBasicBlock;
class Function;
class MachineFunction;
class MachineFunctionInitializer;
class MMIAddrLabelMap;
class Module;
class PointerType;
class StructType;
class TargetMachine;
//===----------------------------------------------------------------------===//
/// This class can be derived from and used by targets to hold private
@ -69,11 +60,12 @@ class StructType;
///
class MachineModuleInfoImpl {
public:
typedef PointerIntPair<MCSymbol*, 1, bool> StubValueTy;
virtual ~MachineModuleInfoImpl();
typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy;
protected:
using StubValueTy = PointerIntPair<MCSymbol *, 1, bool>;
using SymbolListTy = std::vector<std::pair<MCSymbol *, StubValueTy>>;
virtual ~MachineModuleInfoImpl();
protected:
/// Return the entries from a DenseMap in a deterministic sorted orer.
/// Clears the map.
static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);
@ -252,6 +244,6 @@ class MachineModuleInfo : public ImmutablePass {
/// which will link in MSVCRT's floating-point support.
void computeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo &MMI);
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEMODULEINFO_H

View File

@ -133,6 +133,10 @@ namespace llvm {
// instruction and update the MachineFunctionInfo with that information.
extern char &ShrinkWrapID;
/// LiveRangeShrink pass. Move instruction close to its definition to shrink
/// the definition's live range.
extern char &LiveRangeShrinkID;
/// Greedy register allocator.
extern char &RAGreedyID;

View File

@ -22,7 +22,7 @@ namespace llvm {
class PassConfigImpl;
class ScheduleDAGInstrs;
class TargetMachine;
class LLVMTargetMachine;
struct MachineSchedContext;
// The old pass manager infrastructure is hidden in a legacy namespace now.
@ -103,7 +103,7 @@ class TargetPassConfig : public ImmutablePass {
bool AddingMachinePasses;
protected:
TargetMachine *TM;
LLVMTargetMachine *TM;
PassConfigImpl *Impl; // Internal data structures
bool Initialized; // Flagged after all passes are configured.
@ -120,7 +120,7 @@ class TargetPassConfig : public ImmutablePass {
bool RequireCodeGenSCCOrder;
public:
TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm);
// Dummy constructor.
TargetPassConfig();

View File

@ -6,6 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines constants and basic types describing CodeView debug information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEW_H
@ -22,28 +26,28 @@ namespace codeview {
/// documentation and headers talk about this as the "leaf" type.
enum class TypeRecordKind : uint16_t {
#define TYPE_RECORD(lf_ename, value, name) name = value,
#include "TypeRecords.def"
#include "CodeViewTypes.def"
};
/// Duplicate copy of the above enum, but using the official CV names. Useful
/// for reference purposes and when dealing with unknown record types.
enum TypeLeafKind : uint16_t {
#define CV_TYPE(name, val) name = val,
#include "TypeRecords.def"
#include "CodeViewTypes.def"
};
/// Distinguishes individual records in the Symbols subsection of a .debug$S
/// section. Equivalent to SYM_ENUM_e in cvinfo.h.
enum class SymbolRecordKind : uint16_t {
#define SYMBOL_RECORD(lf_ename, value, name) name = value,
#include "CVSymbolTypes.def"
#include "CodeViewSymbols.def"
};
/// Duplicate copy of the above enum, but using the official CV names. Useful
/// for reference purposes and when dealing with unknown record types.
enum SymbolKind : uint16_t {
#define CV_SYMBOL(name, val) name = val,
#include "CVSymbolTypes.def"
#include "CodeViewSymbols.def"
};
#define CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \
@ -280,7 +284,7 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions)
/// Equivalent to CV_LABEL_TYPE_e.
enum class LabelType : uint16_t {
Near = 0x0,
Far = 0x4,
Far = 0x4,
};
/// Equivalent to CV_modifier_t.

View File

@ -34,6 +34,17 @@ class SymbolDeserializer : public SymbolVisitorCallbacks {
};
public:
template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) {
SymbolDeserializer S(nullptr);
if (auto EC = S.visitSymbolBegin(Symbol))
return EC;
if (auto EC = S.visitKnownRecord(Symbol, Record))
return EC;
if (auto EC = S.visitSymbolEnd(Symbol))
return EC;
return Error::success();
}
explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate)
: Delegate(Delegate) {}
@ -54,7 +65,7 @@ class SymbolDeserializer : public SymbolVisitorCallbacks {
return visitKnownRecordImpl(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) {

View File

@ -35,8 +35,6 @@ class SymbolRecord {
public:
SymbolRecordKind getKind() const { return Kind; }
private:
SymbolRecordKind Kind;
};

View File

@ -29,7 +29,7 @@ class SymbolRecordMapping : public SymbolVisitorCallbacks {
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
Optional<SymbolKind> Kind;

View File

@ -45,6 +45,17 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
}
public:
template <typename SymType>
static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage) {
CVSymbol Result;
Result.Type = static_cast<SymbolKind>(Sym.Kind);
SymbolSerializer Serializer(Storage);
consumeError(Serializer.visitSymbolBegin(Result));
consumeError(Serializer.visitKnownRecord(Result, Sym));
consumeError(Serializer.visitSymbolEnd(Result));
return Result;
}
explicit SymbolSerializer(BumpPtrAllocator &Storage);
virtual Error visitSymbolBegin(CVSymbol &Record) override;
@ -55,7 +66,7 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
return visitKnownRecordImpl(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
template <typename RecordKind>

View File

@ -59,7 +59,7 @@ class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks {
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
private:
std::vector<SymbolVisitorCallbacks *> Pipeline;

View File

@ -39,7 +39,7 @@ class SymbolVisitorCallbacks {
return Error::success(); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
};
} // end namespace codeview

View File

@ -39,7 +39,7 @@ class TypeDatabaseVisitor : public TypeVisitorCallbacks {
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"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
StringRef getTypeName(TypeIndex Index) const;

View File

@ -41,6 +41,7 @@ class TypeDeserializer : public TypeVisitorCallbacks {
TypeDeserializer() = default;
template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
MappingInfo I(CVT.content());
if (auto EC = I.Mapping.visitTypeBegin(CVT))
return EC;
@ -75,7 +76,7 @@ class TypeDeserializer : public TypeVisitorCallbacks {
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordType>
@ -127,7 +128,7 @@ class FieldListDeserializer : public TypeVisitorCallbacks {
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordType>

View File

@ -58,7 +58,7 @@ class TypeDumpVisitor : public TypeVisitorCallbacks {
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"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
void printMemberAttributes(MemberAttributes Attrs);

View File

@ -123,13 +123,13 @@ class TypeRecord {
public:
TypeRecordKind getKind() const { return Kind; }
private:
TypeRecordKind Kind;
};
// LF_MODIFIER
class ModifierRecord : public TypeRecord {
public:
ModifierRecord() = default;
explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
@ -145,6 +145,7 @@ class ModifierRecord : public TypeRecord {
// LF_PROCEDURE
class ProcedureRecord : public TypeRecord {
public:
ProcedureRecord() = default;
explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
@ -169,6 +170,7 @@ class ProcedureRecord : public TypeRecord {
// LF_MFUNCTION
class MemberFunctionRecord : public TypeRecord {
public:
MemberFunctionRecord() = default;
explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
@ -203,6 +205,7 @@ class MemberFunctionRecord : public TypeRecord {
// LF_LABEL
class LabelRecord : public TypeRecord {
public:
LabelRecord() = default;
explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
@ -213,6 +216,7 @@ class LabelRecord : public TypeRecord {
// LF_MFUNC_ID
class MemberFuncIdRecord : public TypeRecord {
public:
MemberFuncIdRecord() = default;
explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
StringRef Name)
@ -230,6 +234,7 @@ class MemberFuncIdRecord : public TypeRecord {
// LF_ARGLIST
class ArgListRecord : public TypeRecord {
public:
ArgListRecord() = default;
explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
@ -243,6 +248,7 @@ class ArgListRecord : public TypeRecord {
// LF_SUBSTR_LIST
class StringListRecord : public TypeRecord {
public:
StringListRecord() = default;
explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
@ -267,6 +273,7 @@ class PointerRecord : public TypeRecord {
static const uint32_t PointerSizeShift = 13;
static const uint32_t PointerSizeMask = 0xFF;
PointerRecord() = default;
explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
PointerRecord(TypeIndex ReferentType, uint32_t Attrs)
@ -341,6 +348,7 @@ class PointerRecord : public TypeRecord {
// LF_NESTTYPE
class NestedTypeRecord : public TypeRecord {
public:
NestedTypeRecord() = default;
explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
NestedTypeRecord(TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
@ -355,6 +363,7 @@ class NestedTypeRecord : public TypeRecord {
// LF_FIELDLIST
class FieldListRecord : public TypeRecord {
public:
FieldListRecord() = default;
explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
explicit FieldListRecord(ArrayRef<uint8_t> Data)
: TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
@ -365,6 +374,7 @@ class FieldListRecord : public TypeRecord {
// LF_ARRAY
class ArrayRecord : public TypeRecord {
public:
ArrayRecord() = default;
explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
StringRef Name)
@ -384,6 +394,7 @@ class ArrayRecord : public TypeRecord {
class TagRecord : public TypeRecord {
protected:
TagRecord() = default;
explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, StringRef Name, StringRef UniqueName)
@ -416,6 +427,7 @@ class TagRecord : public TypeRecord {
// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
class ClassRecord : public TagRecord {
public:
ClassRecord() = default;
explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, TypeIndex DerivationList,
@ -447,6 +459,7 @@ class ClassRecord : public TagRecord {
// LF_UNION
struct UnionRecord : public TagRecord {
UnionRecord() = default;
explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
uint64_t Size, StringRef Name, StringRef UniqueName)
@ -468,6 +481,7 @@ struct UnionRecord : public TagRecord {
// LF_ENUM
class EnumRecord : public TagRecord {
public:
EnumRecord() = default;
explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
@ -482,6 +496,7 @@ class EnumRecord : public TagRecord {
// LF_BITFIELD
class BitFieldRecord : public TypeRecord {
public:
BitFieldRecord() = default;
explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
@ -498,6 +513,7 @@ class BitFieldRecord : public TypeRecord {
// LF_VTSHAPE
class VFTableShapeRecord : public TypeRecord {
public:
VFTableShapeRecord() = default;
explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
@ -518,6 +534,7 @@ class VFTableShapeRecord : public TypeRecord {
// LF_TYPESERVER2
class TypeServer2Record : public TypeRecord {
public:
TypeServer2Record() = default;
explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
: TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
@ -537,6 +554,7 @@ class TypeServer2Record : public TypeRecord {
// LF_STRING_ID
class StringIdRecord : public TypeRecord {
public:
StringIdRecord() = default;
explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StringIdRecord(TypeIndex Id, StringRef String)
: TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
@ -551,6 +569,7 @@ class StringIdRecord : public TypeRecord {
// LF_FUNC_ID
class FuncIdRecord : public TypeRecord {
public:
FuncIdRecord() = default;
explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
: TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
@ -570,6 +589,7 @@ class FuncIdRecord : public TypeRecord {
// LF_UDT_SRC_LINE
class UdtSourceLineRecord : public TypeRecord {
public:
UdtSourceLineRecord() = default;
explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
@ -587,6 +607,7 @@ class UdtSourceLineRecord : public TypeRecord {
// LF_UDT_MOD_SRC_LINE
class UdtModSourceLineRecord : public TypeRecord {
public:
UdtModSourceLineRecord() = default;
explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
uint32_t LineNumber, uint16_t Module)
@ -607,6 +628,7 @@ class UdtModSourceLineRecord : public TypeRecord {
// LF_BUILDINFO
class BuildInfoRecord : public TypeRecord {
public:
BuildInfoRecord() = default;
explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
: TypeRecord(TypeRecordKind::BuildInfo),
@ -619,6 +641,7 @@ class BuildInfoRecord : public TypeRecord {
// LF_VFTABLE
class VFTableRecord : public TypeRecord {
public:
VFTableRecord() = default;
explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
uint32_t VFPtrOffset, StringRef Name,
@ -646,7 +669,7 @@ class VFTableRecord : public TypeRecord {
// LF_ONEMETHOD
class OneMethodRecord : public TypeRecord {
public:
OneMethodRecord() : TypeRecord(TypeRecordKind::OneMethod) {}
OneMethodRecord() = default;
explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset,
StringRef Name)
@ -678,6 +701,7 @@ class OneMethodRecord : public TypeRecord {
// LF_METHODLIST
class MethodOverloadListRecord : public TypeRecord {
public:
MethodOverloadListRecord() = default;
explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
@ -689,6 +713,7 @@ class MethodOverloadListRecord : public TypeRecord {
/// For method overload sets. LF_METHOD
class OverloadedMethodRecord : public TypeRecord {
public:
OverloadedMethodRecord() = default;
explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
StringRef Name)
@ -706,6 +731,7 @@ class OverloadedMethodRecord : public TypeRecord {
// LF_MEMBER
class DataMemberRecord : public TypeRecord {
public:
DataMemberRecord() = default;
explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset,
StringRef Name)
@ -730,6 +756,7 @@ class DataMemberRecord : public TypeRecord {
// LF_STMEMBER
class StaticDataMemberRecord : public TypeRecord {
public:
StaticDataMemberRecord() = default;
explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type),
@ -750,6 +777,7 @@ class StaticDataMemberRecord : public TypeRecord {
// LF_ENUMERATE
class EnumeratorRecord : public TypeRecord {
public:
EnumeratorRecord() = default;
explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name)
: TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs),
@ -770,6 +798,7 @@ class EnumeratorRecord : public TypeRecord {
// LF_VFUNCTAB
class VFPtrRecord : public TypeRecord {
public:
VFPtrRecord() = default;
explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VFPtrRecord(TypeIndex Type)
: TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
@ -782,6 +811,7 @@ class VFPtrRecord : public TypeRecord {
// LF_BCLASS, LF_BINTERFACE
class BaseClassRecord : public TypeRecord {
public:
BaseClassRecord() = default;
explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset)
: TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type),
@ -802,6 +832,7 @@ class BaseClassRecord : public TypeRecord {
// LF_VBCLASS, LF_IVBCLASS
class VirtualBaseClassRecord : public TypeRecord {
public:
VirtualBaseClassRecord() = default;
explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs,
TypeIndex BaseType, TypeIndex VBPtrType,
@ -831,6 +862,7 @@ class VirtualBaseClassRecord : public TypeRecord {
/// together. The first will end in an LF_INDEX record that points to the next.
class ListContinuationRecord : public TypeRecord {
public:
ListContinuationRecord() = default;
explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ListContinuationRecord(TypeIndex ContinuationIndex)
: TypeRecord(TypeRecordKind::ListContinuation),

View File

@ -37,7 +37,7 @@ class TypeRecordMapping : public TypeVisitorCallbacks {
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"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
Optional<TypeLeafKind> TypeKind;

View File

@ -106,7 +106,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
return visitKnownMemberImpl<Name##Record>(CVR, Record); \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordKind>

View File

@ -13,8 +13,8 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include <algorithm>

View File

@ -94,7 +94,7 @@ class TypeVisitorCallbackPipeline : public TypeVisitorCallbacks {
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename T> Error visitKnownRecordImpl(CVType &CVR, T &Record) {

View File

@ -58,7 +58,11 @@ class TypeVisitorCallbacks {
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
#undef TYPE_RECORD
#undef TYPE_RECORD_ALIAS
#undef MEMBER_RECORD
#undef MEMBER_RECORD_ALIAS
};
} // end namespace codeview

View File

@ -146,6 +146,14 @@ enum DIDumpType {
DIDT_TUIndex,
};
/// Container for dump options that control which debug information will be
/// dumped.
struct DIDumpOptions {
DIDumpType DumpType = DIDT_All;
bool DumpEH = false;
bool SummarizeTypes = false;
};
class DIContext {
public:
enum DIContextKind {
@ -158,8 +166,7 @@ class DIContext {
DIContextKind getKind() const { return Kind; }
virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false, bool SummarizeTypes = false) = 0;
virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
virtual bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) {
// No verifier? Just say things went well.

View File

@ -105,8 +105,7 @@ class DWARFContext : public DIContext {
return DICtx->getKind() == CK_DWARF;
}
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false, bool SummarizeTypes = false) override;
void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override;
bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;

View File

@ -12,7 +12,6 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include <cstdint>
namespace llvm {

View File

@ -38,7 +38,7 @@ class TpiHashUpdater : public codeview::TypeVisitorCallbacks {
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
private:
template <typename RecordKind>

View File

@ -41,8 +41,7 @@ namespace pdb {
return DICtx->getKind() == CK_PDB;
}
void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All,
bool DumpEH = false, bool SummarizeTypes = false) override;
void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override;
DILineInfo getLineInfoForAddress(
uint64_t Address,

View File

@ -228,34 +228,31 @@ class AttributeSet {
bool operator==(const AttributeSet &O) { return SetNode == O.SetNode; }
bool operator!=(const AttributeSet &O) { return !(*this == O); }
/// Add an argument attribute. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const;
/// Add an argument attribute. Returns a new set because attribute sets are
/// immutable.
AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const;
/// Add a target-dependent attribute. Because
/// attribute sets are immutable, this returns a new set.
/// Add a target-dependent attribute. Returns a new set because attribute sets
/// are immutable.
AttributeSet addAttribute(LLVMContext &C, StringRef Kind,
StringRef Value = StringRef()) const;
/// Add attributes to the attribute set. Because
/// attribute sets are immutable, this returns a new set.
/// Add attributes to the attribute set. Returns a new set because attribute
/// sets are immutable.
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const;
/// Remove the specified attribute from this set. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet removeAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const;
/// Remove the specified attribute from this set. Returns a new set because
/// attribute sets are immutable.
AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const;
/// Remove the specified attribute from this set. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet removeAttribute(LLVMContext &C,
StringRef Kind) const;
/// Remove the specified attribute from this set. Returns a new set because
/// attribute sets are immutable.
AttributeSet removeAttribute(LLVMContext &C, StringRef Kind) const;
/// Remove the specified attributes from this set. Because
/// attribute sets are immutable, this returns a new set.
/// Remove the specified attributes from this set. Returns a new set because
/// attribute sets are immutable.
AttributeSet removeAttributes(LLVMContext &C,
const AttrBuilder &AttrsToRemove) const;
const AttrBuilder &AttrsToRemove) const;
/// Return the number of attributes in this set.
unsigned getNumAttributes() const;
@ -377,6 +374,25 @@ class AttributeList {
static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
/// \brief Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
/// \brief Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
StringRef Value = StringRef()) const;
/// Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute A) const;
/// \brief Add attributes to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &B) const;
/// Add an argument attribute to the list. Returns a new list because
/// attribute lists are immutable.
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
@ -384,66 +400,112 @@ class AttributeList {
return addAttribute(C, ArgNo + FirstArgIndex, Kind);
}
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeList addAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
/// Add an argument attribute to the list. Returns a new list because
/// attribute lists are immutable.
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
StringRef Kind,
StringRef Value = StringRef()) const {
return addAttribute(C, ArgNo + FirstArgIndex, Kind, Value);
}
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
StringRef Value = StringRef()) const;
/// Add an attribute to the attribute list at the given arg indices. Returns a
/// new list because attribute lists are immutable.
AttributeList addParamAttribute(LLVMContext &C, ArrayRef<unsigned> ArgNos,
Attribute A) const;
/// Add an attribute to the attribute set at the given indices. Because
/// attribute sets are immutable, this returns a new set.
AttributeList addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
Attribute A) const;
/// \brief Add attributes to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeList addAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &B) const;
/// Add an argument attribute to the list. Returns a new list because
/// attribute lists are immutable.
AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo,
const AttrBuilder &B) const {
return addAttributes(C, ArgNo + FirstArgIndex, B);
}
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const;
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttribute(LLVMContext &C, unsigned Index,
StringRef Kind) const;
/// \brief Remove the specified attributes at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &AttrsToRemove) const;
/// \brief Remove all attributes at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;
/// \brief Add the dereferenceable attribute to the attribute set at the given
/// index. Because attribute sets are immutable, this returns a new set.
/// \brief Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
Attribute::AttrKind Kind) const {
return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
}
/// \brief Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo,
StringRef Kind) const {
return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
}
/// \brief Remove the specified attribute at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo,
const AttrBuilder &AttrsToRemove) const {
return removeAttributes(C, ArgNo + FirstArgIndex, AttrsToRemove);
}
/// \brief Remove all attributes at the specified arg index from this
/// attribute list. Returns a new list because attribute lists are immutable.
AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo) const {
return removeAttributes(C, ArgNo + FirstArgIndex);
}
/// \Brief Add the dereferenceable attribute to the attribute set at the given
/// index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
/// \Brief Add the dereferenceable attribute to the attribute set at the given
/// arg index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo,
uint64_t Bytes) const {
return addDereferenceableAttr(C, ArgNo + FirstArgIndex, Bytes);
}
/// \brief Add the dereferenceable_or_null attribute to the attribute set at
/// the given index. Because attribute sets are immutable, this returns a new
/// set.
/// the given index. Returns a new list because attribute lists are immutable.
AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const;
/// \brief Add the dereferenceable_or_null attribute to the attribute set at
/// the given arg index. Returns a new list because attribute lists are
/// immutable.
AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C,
unsigned ArgNo,
uint64_t Bytes) const {
return addDereferenceableOrNullAttr(C, ArgNo + FirstArgIndex, Bytes);
}
/// Add the allocsize attribute to the attribute set at the given index.
/// Because attribute sets are immutable, this returns a new set.
/// Returns a new list because attribute lists are immutable.
AttributeList addAllocSizeAttr(LLVMContext &C, unsigned Index,
unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg);
/// Add the allocsize attribute to the attribute set at the given arg index.
/// Returns a new list because attribute lists are immutable.
AttributeList addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo,
unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg) {
return addAllocSizeAttr(C, ArgNo + FirstArgIndex, ElemSizeArg, NumElemsArg);
}
//===--------------------------------------------------------------------===//
// AttributeList Accessors
//===--------------------------------------------------------------------===//
@ -473,6 +535,21 @@ class AttributeList {
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
/// \brief Return true if the attribute exists for the given argument
bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
return hasAttribute(ArgNo + FirstArgIndex, Kind);
}
/// \brief Return true if the attribute exists for the given argument
bool hasParamAttr(unsigned ArgNo, StringRef Kind) const {
return hasAttribute(ArgNo + FirstArgIndex, Kind);
}
/// \brief Return true if attributes exists for the given argument
bool hasParamAttrs(unsigned ArgNo) const {
return hasAttributes(ArgNo + FirstArgIndex);
}
/// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(Attribute::AttrKind Kind) const;
@ -496,6 +573,16 @@ class AttributeList {
/// \brief Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, StringRef Kind) const;
/// \brief Return the attribute object that exists at the arg index.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
return getAttribute(ArgNo + FirstArgIndex, Kind);
}
/// \brief Return the attribute object that exists at the given index.
Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
return getAttribute(ArgNo + FirstArgIndex, Kind);
}
/// \brief Return the alignment of the return value.
unsigned getRetAlignment() const;
@ -508,10 +595,22 @@ class AttributeList {
/// \brief Get the number of dereferenceable bytes (or zero if unknown).
uint64_t getDereferenceableBytes(unsigned Index) const;
/// \brief Get the number of dereferenceable bytes (or zero if unknown) of an
/// arg.
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
return getDereferenceableBytes(ArgNo + FirstArgIndex);
}
/// \brief Get the number of dereferenceable_or_null bytes (or zero if
/// unknown).
uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
/// \brief Get the number of dereferenceable_or_null bytes (or zero if
/// unknown) of an arg.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
return getDereferenceableOrNullBytes(ArgNo + FirstArgIndex);
}
/// Get the allocsize argument numbers (or pair(0, 0) if unknown).
std::pair<unsigned, Optional<unsigned>>
getAllocSizeArgs(unsigned Index) const;

View File

@ -214,10 +214,6 @@ class Function : public GlobalObject, public ilist_node<Function> {
addAttribute(AttributeList::FunctionIndex, Attr);
}
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
/// @brief Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
removeAttribute(AttributeList::FunctionIndex, Kind);
@ -229,10 +225,6 @@ class Function : public GlobalObject, public ilist_node<Function> {
getContext(), AttributeList::FunctionIndex, Kind));
}
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
/// \brief Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
@ -299,6 +291,15 @@ class Function : public GlobalObject, public ilist_node<Function> {
/// @brief adds the attributes to the list of attributes.
void addAttributes(unsigned i, const AttrBuilder &Attrs);
/// @brief adds the attribute to the list of attributes for the given arg.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// @brief adds the attribute to the list of attributes for the given arg.
void addParamAttr(unsigned ArgNo, Attribute Attr);
/// @brief adds the attributes to the list of attributes for the given arg.
void addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
/// @brief removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@ -308,6 +309,15 @@ class Function : public GlobalObject, public ilist_node<Function> {
/// @brief removes the attributes from the list of attributes.
void removeAttributes(unsigned i, const AttrBuilder &Attrs);
/// @brief removes the attribute from the list of attributes.
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// @brief removes the attribute from the list of attributes.
void removeParamAttr(unsigned ArgNo, StringRef Kind);
/// @brief removes the attribute from the list of attributes.
void removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs);
/// @brief check if an attributes is in the list of attributes.
bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().hasAttribute(i, Kind);
@ -329,10 +339,18 @@ class Function : public GlobalObject, public ilist_node<Function> {
/// @brief adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
/// @brief adds the dereferenceable attribute to the list of attributes for
/// the given arg.
void addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes);
/// @brief adds the dereferenceable_or_null attribute to the list of
/// attributes.
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
/// @brief adds the dereferenceable_or_null attribute to the list of
/// attributes for the given arg.
void addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes);
/// @brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned ArgNo) const {
return AttributeSets.getParamAlignment(ArgNo);
@ -345,6 +363,12 @@ class Function : public GlobalObject, public ilist_node<Function> {
return AttributeSets.getDereferenceableBytes(i);
}
/// @brief Extract the number of dereferenceable bytes for a parameter.
/// @param ArgNo Index of an argument, with 0 being the first function arg.
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
return AttributeSets.getParamDereferenceableBytes(ArgNo);
}
/// @brief Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
/// @param i AttributeList index, referring to a return value or argument.
@ -352,6 +376,13 @@ class Function : public GlobalObject, public ilist_node<Function> {
return AttributeSets.getDereferenceableOrNullBytes(i);
}
/// @brief Extract the number of dereferenceable_or_null bytes for a
/// parameter.
/// @param ArgNo AttributeList ArgNo, referring to an argument.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
return AttributeSets.getParamDereferenceableOrNullBytes(ArgNo);
}
/// @brief Determine if the function does not access memory.
bool doesNotAccessMemory() const {
return hasFnAttribute(Attribute::ReadNone);

View File

@ -1660,6 +1660,9 @@ class CallInst : public Instruction,
/// Adds the attribute to the indicated argument
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// Adds the attribute to the indicated argument
void addParamAttr(unsigned ArgNo, Attribute Attr);
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@ -1669,6 +1672,9 @@ class CallInst : public Instruction,
/// Removes the attribute from the given argument
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// Removes the attribute from the given argument
void removeParamAttr(unsigned ArgNo, StringRef Kind);
/// adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@ -1704,6 +1710,18 @@ class CallInst : public Instruction,
return getAttributes().getAttribute(i, Kind);
}
/// Get the attribute of a given kind from a given arg
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
return getAttributes().getParamAttr(ArgNo, Kind);
}
/// Get the attribute of a given kind from a given arg
Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
return getAttributes().getParamAttr(ArgNo, Kind);
}
/// Return true if the data operand at index \p i has the attribute \p
/// A.
///

View File

@ -188,6 +188,7 @@ void initializeLintPass(PassRegistry&);
void initializeLiveDebugValuesPass(PassRegistry&);
void initializeLiveDebugVariablesPass(PassRegistry&);
void initializeLiveIntervalsPass(PassRegistry&);
void initializeLiveRangeShrinkPass(PassRegistry&);
void initializeLiveRegMatrixPass(PassRegistry&);
void initializeLiveStacksPass(PassRegistry&);
void initializeLiveVariablesPass(PassRegistry&);

View File

@ -30,11 +30,18 @@
#define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
#include <map>
namespace llvm {
namespace object {
@ -44,23 +51,44 @@ class WindowsResource;
class ResourceEntryRef {
public:
Error moveNext(bool &End);
bool checkTypeString() const { return IsStringType; }
ArrayRef<UTF16> getTypeString() const { return Type; }
uint16_t getTypeID() const { return TypeID; }
bool checkNameString() const { return IsStringName; }
ArrayRef<UTF16> getNameString() const { return Name; }
uint16_t getNameID() const { return NameID; }
uint16_t getLanguage() const { return Suffix->Language; }
private:
friend class WindowsResource;
ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner,
Error &Err);
Error loadNext();
struct HeaderSuffix {
support::ulittle32_t DataVersion;
support::ulittle16_t MemoryFlags;
support::ulittle16_t Language;
support::ulittle32_t Version;
support::ulittle32_t Characteristics;
};
BinaryStreamReader Reader;
BinaryStreamRef HeaderBytes;
BinaryStreamRef DataBytes;
bool IsStringType;
ArrayRef<UTF16> Type;
uint16_t TypeID;
bool IsStringName;
ArrayRef<UTF16> Name;
uint16_t NameID;
const HeaderSuffix *Suffix = nullptr;
ArrayRef<uint8_t> Data;
const WindowsResource *OwningRes = nullptr;
};
class WindowsResource : public Binary {
public:
~WindowsResource() override;
Expected<ResourceEntryRef> getHeadEntry();
static bool classof(const Binary *V) { return V->isWinRes(); }
@ -76,6 +104,36 @@ class WindowsResource : public Binary {
BinaryByteStream BBS;
};
class WindowsResourceParser {
public:
WindowsResourceParser();
Error parse(WindowsResource *WR);
void printTree() const;
private:
class TreeNode {
public:
TreeNode() = default;
explicit TreeNode(ArrayRef<UTF16> Ref);
void addEntry(const ResourceEntryRef &Entry);
void print(ScopedPrinter &Writer, StringRef Name) const;
private:
TreeNode &addTypeNode(const ResourceEntryRef &Entry);
TreeNode &addNameNode(const ResourceEntryRef &Entry);
TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
TreeNode &addChild(uint32_t ID);
TreeNode &addChild(ArrayRef<UTF16> NameRef);
std::vector<UTF16> Name;
std::map<uint32_t, std::unique_ptr<TreeNode>> IDChildren;
std::map<std::string, std::unique_ptr<TreeNode>> StringChildren;
};
TreeNode Root;
};
} // namespace object
} // namespace llvm

View File

@ -0,0 +1,91 @@
//===- CodeViewYAMLDebugSections.h - CodeView YAMLIO debug sections -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines classes for handling the YAML representation of CodeView
// Debug Info.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLDEBUGSECTIONS_H
#define LLVM_OBJECTYAML_CODEVIEWYAMLDEBUGSECTIONS_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/ObjectYAML/YAML.h"
namespace llvm {
namespace CodeViewYAML {
namespace detail {
struct C13FragmentBase;
}
struct SourceLineEntry {
uint32_t Offset;
uint32_t LineStart;
uint32_t EndDelta;
bool IsStatement;
};
struct SourceColumnEntry {
uint16_t StartColumn;
uint16_t EndColumn;
};
struct SourceLineBlock {
StringRef FileName;
std::vector<SourceLineEntry> Lines;
std::vector<SourceColumnEntry> Columns;
};
struct HexFormattedString {
std::vector<uint8_t> Bytes;
};
struct SourceFileChecksumEntry {
StringRef FileName;
codeview::FileChecksumKind Kind;
HexFormattedString ChecksumBytes;
};
struct SourceLineInfo {
uint32_t RelocOffset;
uint32_t RelocSegment;
codeview::LineFlags Flags;
uint32_t CodeSize;
std::vector<SourceLineBlock> Blocks;
};
struct InlineeSite {
uint32_t Inlinee;
StringRef FileName;
uint32_t SourceLineNum;
std::vector<StringRef> ExtraFiles;
};
struct InlineeInfo {
bool HasExtraFiles;
std::vector<InlineeSite> Sites;
};
struct SourceFileInfo {
std::vector<SourceFileChecksumEntry> FileChecksums;
std::vector<SourceLineInfo> LineFragments;
std::vector<InlineeInfo> Inlinees;
};
struct C13DebugSection {
std::vector<detail::C13FragmentBase> Fragments;
};
} // namespace CodeViewYAML
} // namespace llvm
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileInfo)
#endif

View File

@ -0,0 +1,41 @@
//===- CodeViewYAMLSymbols.h - CodeView YAMLIO Symbol implementation ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines classes for handling the YAML representation of CodeView
// Debug Info.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLSYMBOLS_H
#define LLVM_OBJECTYAML_CODEVIEWYAMLSYMBOLS_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/ObjectYAML/YAML.h"
namespace llvm {
namespace CodeViewYAML {
namespace detail {
struct SymbolRecordBase;
}
struct SymbolRecord {
std::shared_ptr<detail::SymbolRecordBase> Symbol;
codeview::CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator) const;
static Expected<SymbolRecord> fromCodeViewSymbol(codeview::CVSymbol Symbol);
};
} // namespace CodeViewYAML
} // namespace llvm
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SymbolRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::SymbolRecord)
#endif

View File

@ -0,0 +1,48 @@
//===- CodeViewYAMLTypes.h - CodeView YAMLIO Type Record implementation ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines classes for handling the YAML representation of CodeView
// Debug Info.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECTYAML_CODEVIEWYAMLTYPES_H
#define LLVM_OBJECTYAML_CODEVIEWYAMLTYPES_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/ObjectYAML/YAML.h"
namespace llvm {
namespace CodeViewYAML {
namespace detail {
struct LeafRecordBase;
struct MemberRecordBase;
}
struct MemberRecord {
std::shared_ptr<detail::MemberRecordBase> Member;
};
struct LeafRecord {
std::shared_ptr<detail::LeafRecordBase> Leaf;
codeview::CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const;
static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
};
} // namespace CodeViewYAML
} // namespace llvm
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::LeafRecord)
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::MemberRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::LeafRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::MemberRecord)
#endif

View File

@ -192,6 +192,39 @@ class PassBuilder {
buildFunctionSimplificationPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Construct the core LLVM module canonicalization and simplification
/// pipeline.
///
/// This pipeline focuses on canonicalizing and simplifying the entire module
/// of IR. Much like the function simplification pipeline above, it is
/// suitable to run repeatedly over the IR and is not expected to destroy
/// important information. It does, however, perform inlining and other
/// heuristic based simplifications that are not strictly reversible.
///
/// Note that \p Level cannot be `O0` here. The pipelines produced are
/// only intended for use when attempting to optimize code. If frontends
/// require some transformations for semantic reasons, they should explicitly
/// build them.
ModulePassManager
buildModuleSimplificationPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Construct the core LLVM module optimization pipeline.
///
/// This pipeline focuses on optimizing the execution speed of the IR. It
/// uses cost modeling and thresholds to balance code growth against runtime
/// improvements. It includes vectorization and other information destroying
/// transformations. It also cannot generally be run repeatedly on a module
/// without potentially seriously regressing either runtime performance of
/// the code or serious code size growth.
///
/// Note that \p Level cannot be `O0` here. The pipelines produced are
/// only intended for use when attempting to optimize code. If frontends
/// require some transformations for semantic reasons, they should explicitly
/// build them.
ModulePassManager buildModuleOptimizationPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Build a per-module default optimization pipeline.
///
/// This provides a good default optimization pipeline for per-module
@ -206,6 +239,36 @@ class PassBuilder {
ModulePassManager buildPerModuleDefaultPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Build a pre-link, ThinLTO-targeting default optimization pipeline to
/// a pass manager.
///
/// This adds the pre-link optimizations tuned to prepare a module for
/// a ThinLTO run. It works to minimize the IR which needs to be analyzed
/// without making irreversible decisions which could be made better during
/// the LTO run.
///
/// Note that \p Level cannot be `O0` here. The pipelines produced are
/// only intended for use when attempting to optimize code. If frontends
/// require some transformations for semantic reasons, they should explicitly
/// build them.
ModulePassManager
buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Build an ThinLTO default optimization pipeline to a pass manager.
///
/// This provides a good default optimization pipeline for link-time
/// optimization and code generation. It is particularly tuned to fit well
/// when IR coming into the LTO phase was first run through \c
/// addPreLinkLTODefaultPipeline, and the two coordinate closely.
///
/// Note that \p Level cannot be `O0` here. The pipelines produced are
/// only intended for use when attempting to optimize code. If frontends
/// require some transformations for semantic reasons, they should explicitly
/// build them.
ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level,
bool DebugLogging = false);
/// Build a pre-link, LTO-targeting default optimization pipeline to a pass
/// manager.
///

View File

@ -206,7 +206,7 @@ ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false,
ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC)
ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, false, ARM::AEK_SEC)
ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP))
ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
@ -236,7 +236,7 @@ ARM_CPU_NAME("cortex-m23", AK_ARMV8MBaseline, FK_NONE, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m33", AK_ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP)
ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)

View File

@ -14,6 +14,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/type_traits.h"
@ -104,6 +105,13 @@ class BinaryStreamReader {
/// returns an appropriate error code.
Error readCString(StringRef &Dest);
/// Similar to readCString, however read a null-terminated UTF16 string
/// instead.
///
/// \returns a success error code if the data was successfully read, otherwise
/// returns an appropriate error code.
Error readWideString(ArrayRef<UTF16> &Dest);
/// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
/// on the implementation of the underlying stream. Updates the stream's
/// offset to point after the newly read data.

View File

@ -1606,6 +1606,44 @@ template <typename T> struct StdMapStringCustomMappingTraitsImpl {
} \
}
#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
namespace llvm { \
namespace yaml { \
template <> struct MappingTraits<Type> { \
static void mapping(IO &IO, Type &Obj); \
}; \
} \
}
#define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
namespace llvm { \
namespace yaml { \
template <> struct ScalarEnumerationTraits<Type> { \
static void enumeration(IO &io, Type &Value); \
}; \
} \
}
#define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
namespace llvm { \
namespace yaml { \
template <> struct ScalarBitSetTraits<Type> { \
static void bitset(IO &IO, Type &Options); \
}; \
} \
}
#define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
namespace llvm { \
namespace yaml { \
template <> struct ScalarTraits<Type> { \
static void output(const Type &Value, void *ctx, llvm::raw_ostream &Out); \
static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
static bool mustQuote(StringRef) { return MustQuote; } \
}; \
} \
}
/// Utility for declaring that a std::vector of a particular type
/// should be considered a YAML document list.
#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \

View File

@ -1237,7 +1237,6 @@ class RecordVal {
public:
RecordVal(Init *N, RecTy *T, bool P);
RecordVal(StringRef N, RecTy *T, bool P);
StringRef getName() const;
Init *getNameInit() const { return Name; }
@ -1340,7 +1339,6 @@ class Record {
}
void setName(Init *Name); // Also updates RecordKeeper.
void setName(StringRef Name); // Also updates RecordKeeper.
ArrayRef<SMLoc> getLoc() const { return Locs; }
@ -1378,13 +1376,11 @@ class Record {
}
RecordVal *getValue(const Init *Name) {
for (RecordVal &Val : Values)
if (Val.Name == Name) return &Val;
return nullptr;
return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
RecordVal *getValue(StringRef Name) {
return getValue(StringInit::get(Name));
return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
void addTemplateArg(Init *Name) {
@ -1492,7 +1488,7 @@ class Record {
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
///
std::string getValueAsString(StringRef FieldName) const;
StringRef getValueAsString(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
@ -1522,7 +1518,7 @@ class Record {
/// returns its value as a vector of strings, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
std::vector<StringRef> getValueAsListOfStrings(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if

View File

@ -1143,6 +1143,16 @@ class TargetLoweringBase {
return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy;
}
/// Get maximum # of load operations permitted for memcmp
///
/// This function returns the maximum number of load operations permitted
/// to replace a call to memcmp. The value is set by the target at the
/// performance threshold for such a replacement. If OptSize is true,
/// return the limit for functions that have OptSize attribute.
unsigned getMaxExpandSizeMemcmp(bool OptSize) const {
return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp;
}
/// \brief Get maximum # of store operations permitted for llvm.memmove
///
/// This function returns the maximum number of store operations permitted
@ -2330,6 +2340,8 @@ class TargetLoweringBase {
/// Maximum number of store operations that may be substituted for a call to
/// memcpy, used for functions with OptSize attribute.
unsigned MaxStoresPerMemcpyOptSize;
unsigned MaxLoadsPerMemcmp;
unsigned MaxLoadsPerMemcmpOptSize;
/// \brief Specify maximum bytes of store instructions per memmove call.
///

View File

@ -299,6 +299,12 @@ class LLVMTargetMachine : public TargetMachine {
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
raw_pwrite_stream &OS,
bool DisableVerify = true) override;
/// Returns true if the target is expected to pass all machine verifier
/// checks. This is a stopgap measure to fix targets one by one. We will
/// remove this at some point and always enable the verifier when
/// EXPENSIVE_CHECKS is enabled.
virtual bool isMachineVerifierClean() const { return true; }
};
} // end namespace llvm

View File

@ -0,0 +1,41 @@
//===- ThinLTOBitcodeWriter.h - Bitcode writing pass for ThinLTO ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass prepares a module containing type metadata for ThinLTO by splitting
// it into regular and thin LTO parts if possible, and writing both parts to
// a multi-module bitcode file. Modules that do not contain type metadata are
// written unmodified as a single module.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H
#define LLVM_TRANSFORMS_IPO_THINLTOBITCODEWRITER_H
#include <llvm/IR/PassManager.h>
#include <llvm/Support/raw_ostream.h>
namespace llvm {
class ThinLTOBitcodeWriterPass
: public PassInfoMixin<ThinLTOBitcodeWriterPass> {
raw_ostream &OS;
raw_ostream *ThinLinkOS;
public:
// Writes bitcode to OS. Also write thin link file to ThinLinkOS, if
// it's not nullptr.
ThinLTOBitcodeWriterPass(raw_ostream &OS, raw_ostream *ThinLinkOS)
: OS(OS), ThinLinkOS(ThinLinkOS) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
} // namespace llvm
#endif

View File

@ -68,24 +68,6 @@ class GVN : public PassInfoMixin<GVN> {
class ValueTable {
DenseMap<Value *, uint32_t> valueNumbering;
DenseMap<Expression, uint32_t> expressionNumbering;
// Expressions is the vector of Expression. ExprIdx is the mapping from
// value number to the index of Expression in Expressions. We use it
// instead of a DenseMap because filling such mapping is faster than
// filling a DenseMap and the compile time is a little better.
uint32_t nextExprNumber;
std::vector<Expression> Expressions;
std::vector<uint32_t> ExprIdx;
// Value number to PHINode mapping. Used for phi-translate in scalarpre.
DenseMap<uint32_t, PHINode *> NumberingPhi;
// Cache for phi-translate in scalarpre.
typedef DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>
PhiTranslateMap;
PhiTranslateMap PhiTranslateTable;
// Map the block to reversed postorder traversal number. It is used to
// find back edge easily.
DenseMap<const BasicBlock *, uint32_t> BlockRPONumber;
AliasAnalysis *AA;
MemoryDependenceResults *MD;
DominatorTree *DT;
@ -97,10 +79,6 @@ class GVN : public PassInfoMixin<GVN> {
Value *LHS, Value *RHS);
Expression createExtractvalueExpr(ExtractValueInst *EI);
uint32_t lookupOrAddCall(CallInst *C);
uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
uint32_t Num, GVN &Gvn);
std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
public:
ValueTable();
@ -109,12 +87,9 @@ class GVN : public PassInfoMixin<GVN> {
~ValueTable();
uint32_t lookupOrAdd(Value *V);
uint32_t lookup(Value *V, bool Verify = true) const;
uint32_t lookup(Value *V) const;
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
Value *LHS, Value *RHS);
uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
uint32_t Num, GVN &Gvn);
void assignBlockRPONumber(Function &F);
bool exists(Value *V) const;
void add(Value *V, uint32_t num);
void clear();

View File

@ -25,6 +25,7 @@ template <typename T> class ArrayRef;
class BranchProbabilityInfo;
class DominatorTree;
class Function;
class Instruction;
class Loop;
class Module;
class RegionNode;
@ -103,7 +104,17 @@ template <typename T> class ArrayRef;
/// a code sequence, that sequence is modified, including changing these
/// sets, before extraction occurs. These modifications won't have any
/// significant impact on the cost however.
void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs) const;
void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs,
const ValueSet &Allocas) const;
/// Find the set of allocas whose life ranges are contained within the
/// outlined region.
///
/// Allocas which have life_time markers contained in the outlined region
/// should be pushed to the outlined function. The address bitcasts that
/// are used by the lifetime markers are also candidates for shrink-
/// wrapping. The instructions that need to be sinked are collected in
/// 'Allocas'.
void findAllocas(ValueSet &Allocas) const;
private:
void severSplitPHINodes(BasicBlock *&Header);

View File

@ -95,8 +95,8 @@ module LLVM_DebugInfo_CodeView {
module * { export * }
// These are intended for (repeated) textual inclusion.
textual header "DebugInfo/CodeView/TypeRecords.def"
textual header "DebugInfo/CodeView/CVSymbolTypes.def"
textual header "DebugInfo/CodeView/CodeViewTypes.def"
textual header "DebugInfo/CodeView/CodeViewSymbols.def"
}
module LLVM_ExecutionEngine {

View File

@ -210,6 +210,11 @@ template <typename CFLAA> class CFLGraphBuilder {
void addDerefEdge(Value *From, Value *To, bool IsRead) {
assert(From != nullptr && To != nullptr);
// FIXME: This is subtly broken, due to how we model some instructions
// (e.g. extractvalue, extractelement) as loads. Since those take
// non-pointer operands, we'll entirely skip adding edges for those.
//
// addAssignEdge seems to have a similar issue with insertvalue, etc.
if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
return;
addNode(From);
@ -540,6 +545,7 @@ template <typename CFLAA> class CFLGraphBuilder {
case Instruction::ExtractValue: {
auto *Ptr = CE->getOperand(0);
addLoadEdge(Ptr, CE);
break;
}
case Instruction::ShuffleVector: {
auto *From1 = CE->getOperand(0);

View File

@ -1739,6 +1739,7 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
if ((Name == "round" && TLI->has(LibFunc_round)) ||
(Name == "roundf" && TLI->has(LibFunc_roundf)))
return ConstantFoldFP(round, V, Ty);
break;
case 's':
if ((Name == "sin" && TLI->has(LibFunc_sin)) ||
(Name == "sinf" && TLI->has(LibFunc_sinf)))
@ -1807,6 +1808,7 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
/*roundTowardZero=*/false, Ty);
LLVM_FALLTHROUGH;
case Intrinsic::x86_sse_cvttss2si:
case Intrinsic::x86_sse_cvttss2si64:
case Intrinsic::x86_sse2_cvttsd2si:

View File

@ -27,8 +27,10 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
return StringSwitch<EHPersonality>(F->getName())
.Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
.Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
.Case("__gxx_personality_seh0",EHPersonality::GNU_CXX)
.Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
.Case("__gcc_personality_v0", EHPersonality::GNU_C)
.Case("__gcc_personality_seh0",EHPersonality::GNU_C)
.Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
.Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
.Case("_except_handler3", EHPersonality::MSVC_X86SEH)

View File

@ -103,13 +103,8 @@ static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
return false;
// If we have a DominatorTree then do a precise test.
if (DT) {
if (!DT->isReachableFromEntry(P->getParent()))
return true;
if (!DT->isReachableFromEntry(I->getParent()))
return false;
if (DT)
return DT->dominates(I, P);
}
// Otherwise, if the instruction is in the entry block and is not an invoke,
// then it obviously dominates all phi nodes.

View File

@ -691,6 +691,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
// load query, we can safely ignore it (scan past it).
if (isLoad)
continue;
LLVM_FALLTHROUGH;
default:
// Otherwise, there is a potential dependence. Return a clobber.
return MemDepResult::getClobber(Inst);

View File

@ -8182,6 +8182,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
case ICmpInst::ICMP_SGE:
std::swap(LHS, RHS);
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SLE:
// X s<= (X + C)<nsw> if C >= 0
if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) && C.isNonNegative())
@ -8195,6 +8196,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
case ICmpInst::ICMP_SGT:
std::swap(LHS, RHS);
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SLT:
// X s< (X + C)<nsw> if C > 0
if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&
@ -8552,6 +8554,7 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
if (isImpliedCondOperands(Pred, LHS, RHS, V,
getConstant(SharperMin)))
return true;
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_UGT:
@ -8566,6 +8569,7 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min)))
return true;
LLVM_FALLTHROUGH;
default:
// No change

View File

@ -215,6 +215,10 @@ bool TargetTransformInfo::enableAggressiveInterleaving(bool LoopHasReductions) c
return TTIImpl->enableAggressiveInterleaving(LoopHasReductions);
}
bool TargetTransformInfo::expandMemCmp(Instruction *I, unsigned &MaxLoadSize) const {
return TTIImpl->expandMemCmp(I, MaxLoadSize);
}
bool TargetTransformInfo::enableInterleavedAccessVectorization() const {
return TTIImpl->enableInterleavedAccessVectorization();
}

View File

@ -172,6 +172,18 @@ bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
}
bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI) {
for (const User *U : CxtI->users()) {
if (const ICmpInst *IC = dyn_cast<ICmpInst>(U))
if (IC->isEquality())
if (Constant *C = dyn_cast<Constant>(IC->getOperand(1)))
if (C->isNullValue())
continue;
return false;
}
return true;
}
static bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
const Query &Q);
@ -2327,6 +2339,7 @@ bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple,
case Instruction::SExt:
if (!LookThroughSExt) return false;
// otherwise fall through to ZExt
LLVM_FALLTHROUGH;
case Instruction::ZExt:
return ComputeMultiple(I->getOperand(0), Base, Multiple,
LookThroughSExt, Depth+1);

View File

@ -378,18 +378,10 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
ModuleToSummariesForIndex->count(ModulePath);
}
bool hasValueId(GlobalValue::GUID ValGUID) {
const auto &VMI = GUIDToValueIdMap.find(ValGUID);
return VMI != GUIDToValueIdMap.end();
}
void assignValueId(GlobalValue::GUID ValGUID) {
unsigned &ValueId = GUIDToValueIdMap[ValGUID];
if (ValueId == 0)
ValueId = ++GlobalValueId;
}
unsigned getValueId(GlobalValue::GUID ValGUID) {
Optional<unsigned> getValueId(GlobalValue::GUID ValGUID) {
auto VMI = GUIDToValueIdMap.find(ValGUID);
assert(VMI != GUIDToValueIdMap.end());
if (VMI == GUIDToValueIdMap.end())
return None;
return VMI->second;
}
std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; }
@ -3413,12 +3405,6 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
Stream.EmitRecord(bitc::FS_VERSION, ArrayRef<uint64_t>{INDEX_VERSION});
// Create value IDs for undefined references.
forEachSummary([&](GVInfo I) {
for (auto &RI : I.second->refs())
assignValueId(RI.getGUID());
});
for (const auto &GVI : valueIds()) {
Stream.EmitRecord(bitc::FS_VALUE_GUID,
ArrayRef<uint64_t>{GVI.second, GVI.first});
@ -3492,9 +3478,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
GlobalValueSummary *S = I.second;
assert(S);
assert(hasValueId(I.first));
unsigned ValueId = getValueId(I.first);
SummaryToValueIdMap[S] = ValueId;
auto ValueId = getValueId(I.first);
assert(ValueId);
SummaryToValueIdMap[S] = *ValueId;
if (auto *AS = dyn_cast<AliasSummary>(S)) {
// Will process aliases as a post-pass because the reader wants all
@ -3504,11 +3490,14 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
}
if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
NameVals.push_back(ValueId);
NameVals.push_back(*ValueId);
NameVals.push_back(Index.getModuleId(VS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(VS->flags()));
for (auto &RI : VS->refs()) {
NameVals.push_back(getValueId(RI.getGUID()));
auto RefValueId = getValueId(RI.getGUID());
if (!RefValueId)
continue;
NameVals.push_back(*RefValueId);
}
// Emit the finished record.
@ -3522,15 +3511,22 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
auto *FS = cast<FunctionSummary>(S);
writeFunctionTypeMetadataRecords(Stream, FS);
NameVals.push_back(ValueId);
NameVals.push_back(*ValueId);
NameVals.push_back(Index.getModuleId(FS->modulePath()));
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
NameVals.push_back(FS->instCount());
NameVals.push_back(FS->refs().size());
// Fill in below
NameVals.push_back(0);
unsigned Count = 0;
for (auto &RI : FS->refs()) {
NameVals.push_back(getValueId(RI.getGUID()));
auto RefValueId = getValueId(RI.getGUID());
if (!RefValueId)
continue;
NameVals.push_back(*RefValueId);
Count++;
}
NameVals[4] = Count;
bool HasProfileData = false;
for (auto &EI : FS->calls()) {
@ -3543,15 +3539,19 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
// If this GUID doesn't have a value id, it doesn't have a function
// summary and we don't need to record any calls to it.
GlobalValue::GUID GUID = EI.first.getGUID();
if (!hasValueId(GUID)) {
auto CallValueId = getValueId(GUID);
if (!CallValueId) {
// For SamplePGO, the indirect call targets for local functions will
// have its original name annotated in profile. We try to find the
// corresponding PGOFuncName as the GUID.
GUID = Index.getGUIDFromOriginalID(GUID);
if (GUID == 0 || !hasValueId(GUID))
if (GUID == 0)
continue;
CallValueId = getValueId(GUID);
if (!CallValueId)
continue;
}
NameVals.push_back(getValueId(GUID));
NameVals.push_back(*CallValueId);
if (HasProfileData)
NameVals.push_back(static_cast<uint8_t>(EI.second.Hotness));
}

View File

@ -165,7 +165,7 @@ void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
unsigned Reg = *I;
if (!IsReturnBlock && !(Pristine.test(Reg) || BB->isLiveIn(Reg)))
if (!IsReturnBlock && !Pristine.test(Reg))
continue;
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
unsigned AliasReg = *AI;

View File

@ -949,6 +949,19 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
MCConstantExpr::create(FrameOffset, OutContext));
}
static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF,
MachineModuleInfo *MMI) {
if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo())
return true;
// We might emit an EH table that uses function begin and end labels even if
// we don't have any landingpads.
if (!MF.getFunction()->hasPersonalityFn())
return false;
return !isNoOpWithoutInvoke(
classifyEHPersonality(MF.getFunction()->getPersonalityFn()));
}
/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::EmitFunctionBody() {
@ -1076,8 +1089,8 @@ void AsmPrinter::EmitFunctionBody() {
// Emit target-specific gunk after the function body.
EmitFunctionBodyEnd();
if (!MF->getLandingPads().empty() || MMI->hasDebugInfo() ||
MF->hasEHFunclets() || MAI->hasDotTypeDotSizeDirective()) {
if (needFuncLabelsForEHOrDebugInfo(*MF, MMI) ||
MAI->hasDotTypeDotSizeDirective()) {
// Create a symbol for the end of function.
CurrentFnEnd = createTempSymbol("func_end");
OutStreamer->EmitLabel(CurrentFnEnd);
@ -1402,8 +1415,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
CurrentFnBegin = nullptr;
CurExceptionSym = nullptr;
bool NeedsLocalForSize = MAI->needsLocalForSize();
if (!MF.getLandingPads().empty() || MMI->hasDebugInfo() ||
MF.hasEHFunclets() || NeedsLocalForSize) {
if (needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize) {
CurrentFnBegin = createTempSymbol("func_begin");
if (NeedsLocalForSize)
CurrentFnSymForSize = CurrentFnBegin;

View File

@ -309,7 +309,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// If some instruction between the previous try-range and the end of the
// function may throw, create a call-site entry with no landing pad for the
// region following the try-range.
if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) {
if (SawPotentiallyThrowing && !IsSJLJ) {
CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
CallSites.push_back(Site);
}

View File

@ -49,6 +49,7 @@ add_llvm_library(LLVMCodeGen
LivePhysRegs.cpp
LiveRangeCalc.cpp
LiveRangeEdit.cpp
LiveRangeShrink.cpp
LiveRegMatrix.cpp
LiveRegUnits.cpp
LiveStackAnalysis.cpp

View File

@ -43,6 +43,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeLiveDebugValuesPass(Registry);
initializeLiveDebugVariablesPass(Registry);
initializeLiveIntervalsPass(Registry);
initializeLiveRangeShrinkPass(Registry);
initializeLiveStacksPass(Registry);
initializeLiveVariablesPass(Registry);
initializeLocalStackSlotPassPass(Registry);

View File

@ -24,12 +24,13 @@
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@ -60,6 +61,7 @@
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;
using namespace llvm::PatternMatch;
@ -84,6 +86,12 @@ STATISTIC(NumDbgValueMoved, "Number of debug value instructions moved");
STATISTIC(NumSelectsExpanded, "Number of selects turned into branches");
STATISTIC(NumStoreExtractExposed, "Number of store(extractelement) exposed");
STATISTIC(NumMemCmpCalls, "Number of memcmp calls");
STATISTIC(NumMemCmpNotConstant, "Number of memcmp calls without constant size");
STATISTIC(NumMemCmpGreaterThanMax,
"Number of memcmp calls with size greater than max size");
STATISTIC(NumMemCmpInlined, "Number of inlined memcmp calls");
static cl::opt<bool> DisableBranchOpts(
"disable-cgp-branch-opts", cl::Hidden, cl::init(false),
cl::desc("Disable branch optimizations in CodeGenPrepare"));
@ -144,6 +152,11 @@ EnableTypePromotionMerge("cgp-type-promotion-merge", cl::Hidden,
cl::desc("Enable merging of redundant sexts when one is dominating"
" the other."), cl::init(true));
static cl::opt<unsigned> MemCmpNumLoadsPerBlock(
"memcmp-num-loads-per-block", cl::Hidden, cl::init(1),
cl::desc("The number of loads per basic block for inline expansion of "
"memcmp that is only being compared against zero."));
namespace {
typedef SmallPtrSet<Instruction *, 16> SetOfInstrs;
typedef PointerIntPair<Type *, 1, bool> TypeIsSExt;
@ -1629,6 +1642,593 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros,
return true;
}
// This class provides helper functions to expand a memcmp library call into an
// inline expansion.
class MemCmpExpansion {
struct ResultBlock {
BasicBlock *BB;
PHINode *PhiSrc1;
PHINode *PhiSrc2;
ResultBlock();
};
CallInst *CI;
ResultBlock ResBlock;
unsigned MaxLoadSize;
unsigned NumBlocks;
unsigned NumBlocksNonOneByte;
unsigned NumLoadsPerBlock;
std::vector<BasicBlock *> LoadCmpBlocks;
BasicBlock *EndBlock;
PHINode *PhiRes;
bool IsUsedForZeroCmp;
int calculateNumBlocks(unsigned Size);
void createLoadCmpBlocks();
void createResultBlock();
void setupResultBlockPHINodes();
void setupEndBlockPHINodes();
void emitLoadCompareBlock(unsigned Index, int LoadSize, int GEPIndex,
bool IsLittleEndian);
void emitLoadCompareBlockMultipleLoads(unsigned Index, unsigned Size,
unsigned &NumBytesProcessed);
void emitLoadCompareByteBlock(unsigned Index, int GEPIndex);
void emitMemCmpResultBlock(bool IsLittleEndian);
Value *getMemCmpExpansionZeroCase(unsigned Size, bool IsLittleEndian);
unsigned getLoadSize(unsigned Size);
unsigned getNumLoads(unsigned Size);
public:
MemCmpExpansion(CallInst *CI, unsigned MaxLoadSize,
unsigned NumLoadsPerBlock);
Value *getMemCmpExpansion(bool IsLittleEndian);
};
MemCmpExpansion::ResultBlock::ResultBlock()
: BB(nullptr), PhiSrc1(nullptr), PhiSrc2(nullptr) {}
// Initialize the basic block structure required for expansion of memcmp call
// with given maximum load size and memcmp size parameter.
// This structure includes:
// 1. A list of load compare blocks - LoadCmpBlocks.
// 2. An EndBlock, split from original instruction point, which is the block to
// return from.
// 3. ResultBlock, block to branch to for early exit when a
// LoadCmpBlock finds a difference.
MemCmpExpansion::MemCmpExpansion(CallInst *CI, unsigned MaxLoadSize,
unsigned NumLoadsPerBlock)
: CI(CI), MaxLoadSize(MaxLoadSize), NumLoadsPerBlock(NumLoadsPerBlock) {
IRBuilder<> Builder(CI->getContext());
BasicBlock *StartBlock = CI->getParent();
EndBlock = StartBlock->splitBasicBlock(CI, "endblock");
setupEndBlockPHINodes();
IsUsedForZeroCmp = isOnlyUsedInZeroEqualityComparison(CI);
ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
uint64_t Size = SizeCast->getZExtValue();
// Calculate how many load compare blocks are required for an expansion of
// given Size.
NumBlocks = calculateNumBlocks(Size);
createResultBlock();
// If return value of memcmp is not used in a zero equality, we need to
// calculate which source was larger. The calculation requires the
// two loaded source values of each load compare block.
// These will be saved in the phi nodes created by setupResultBlockPHINodes.
if (!IsUsedForZeroCmp)
setupResultBlockPHINodes();
// Create the number of required load compare basic blocks.
createLoadCmpBlocks();
// Update the terminator added by splitBasicBlock to branch to the first
// LoadCmpBlock.
Builder.SetCurrentDebugLocation(CI->getDebugLoc());
StartBlock->getTerminator()->setSuccessor(0, LoadCmpBlocks[0]);
}
void MemCmpExpansion::createLoadCmpBlocks() {
for (unsigned i = 0; i < NumBlocks; i++) {
BasicBlock *BB = BasicBlock::Create(CI->getContext(), "loadbb",
EndBlock->getParent(), EndBlock);
LoadCmpBlocks.push_back(BB);
}
}
void MemCmpExpansion::createResultBlock() {
ResBlock.BB = BasicBlock::Create(CI->getContext(), "res_block",
EndBlock->getParent(), EndBlock);
}
// This function creates the IR instructions for loading and comparing 1 byte.
// It loads 1 byte from each source of the memcmp paramters with the given
// GEPIndex. It then subtracts the two loaded values and adds this result to the
// final phi node for selecting the memcmp result.
void MemCmpExpansion::emitLoadCompareByteBlock(unsigned Index, int GEPIndex) {
IRBuilder<> Builder(CI->getContext());
Value *Source1 = CI->getArgOperand(0);
Value *Source2 = CI->getArgOperand(1);
Builder.SetInsertPoint(LoadCmpBlocks[Index]);
Type *LoadSizeType = Type::getInt8Ty(CI->getContext());
// Cast source to LoadSizeType*
if (Source1->getType() != LoadSizeType)
Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
if (Source2->getType() != LoadSizeType)
Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
// Get the base address using the GEPIndex
if (GEPIndex != 0) {
Source1 = Builder.CreateGEP(LoadSizeType, Source1,
ConstantInt::get(LoadSizeType, GEPIndex));
Source2 = Builder.CreateGEP(LoadSizeType, Source2,
ConstantInt::get(LoadSizeType, GEPIndex));
}
Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
LoadSrc1 = Builder.CreateZExt(LoadSrc1, Type::getInt32Ty(CI->getContext()));
LoadSrc2 = Builder.CreateZExt(LoadSrc2, Type::getInt32Ty(CI->getContext()));
Value *Diff = Builder.CreateSub(LoadSrc1, LoadSrc2);
PhiRes->addIncoming(Diff, LoadCmpBlocks[Index]);
if (Index < (LoadCmpBlocks.size() - 1)) {
// Early exit branch if difference found to EndBlock, otherwise continue to
// next LoadCmpBlock
Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, Diff,
ConstantInt::get(Diff->getType(), 0));
BranchInst *CmpBr =
BranchInst::Create(EndBlock, LoadCmpBlocks[Index + 1], Cmp);
Builder.Insert(CmpBr);
} else {
// The last block has an unconditional branch to EndBlock
BranchInst *CmpBr = BranchInst::Create(EndBlock);
Builder.Insert(CmpBr);
}
}
unsigned MemCmpExpansion::getNumLoads(unsigned Size) {
return (Size / MaxLoadSize) + countPopulation(Size % MaxLoadSize);
}
unsigned MemCmpExpansion::getLoadSize(unsigned Size) {
return MinAlign(PowerOf2Floor(Size), MaxLoadSize);
}
void MemCmpExpansion::emitLoadCompareBlockMultipleLoads(
unsigned Index, unsigned Size, unsigned &NumBytesProcessed) {
IRBuilder<> Builder(CI->getContext());
std::vector<Value *> XorList, OrList;
Value *Diff;
unsigned RemainingBytes = Size - NumBytesProcessed;
unsigned NumLoadsRemaining = getNumLoads(RemainingBytes);
unsigned NumLoads = std::min(NumLoadsRemaining, NumLoadsPerBlock);
Builder.SetInsertPoint(LoadCmpBlocks[Index]);
for (unsigned i = 0; i < NumLoads; ++i) {
unsigned LoadSize = getLoadSize(RemainingBytes);
unsigned GEPIndex = NumBytesProcessed / LoadSize;
NumBytesProcessed += LoadSize;
RemainingBytes -= LoadSize;
Type *LoadSizeType = IntegerType::get(CI->getContext(), LoadSize * 8);
Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
Value *Source1 = CI->getArgOperand(0);
Value *Source2 = CI->getArgOperand(1);
// Cast source to LoadSizeType*
if (Source1->getType() != LoadSizeType)
Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
if (Source2->getType() != LoadSizeType)
Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
// Get the base address using the GEPIndex
if (GEPIndex != 0) {
Source1 = Builder.CreateGEP(LoadSizeType, Source1,
ConstantInt::get(LoadSizeType, GEPIndex));
Source2 = Builder.CreateGEP(LoadSizeType, Source2,
ConstantInt::get(LoadSizeType, GEPIndex));
}
// Load LoadSizeType from the base address
Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
if (LoadSizeType != MaxLoadType) {
LoadSrc1 = Builder.CreateZExtOrTrunc(LoadSrc1, MaxLoadType);
LoadSrc2 = Builder.CreateZExtOrTrunc(LoadSrc2, MaxLoadType);
}
Diff = Builder.CreateXor(LoadSrc1, LoadSrc2);
Diff = Builder.CreateZExtOrTrunc(Diff, MaxLoadType);
XorList.push_back(Diff);
}
auto pairWiseOr = [&](std::vector<Value *> &InList) -> std::vector<Value *> {
std::vector<Value *> OutList;
for (unsigned i = 0; i < InList.size() - 1; i = i + 2) {
Value *Or = Builder.CreateOr(InList[i], InList[i + 1]);
OutList.push_back(Or);
}
if (InList.size() % 2 != 0)
OutList.push_back(InList.back());
return OutList;
};
// Pair wise OR the XOR results
OrList = pairWiseOr(XorList);
// Pair wise OR the OR results until one result left
while (OrList.size() != 1) {
OrList = pairWiseOr(OrList);
}
Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, OrList[0],
ConstantInt::get(Diff->getType(), 0));
BasicBlock *NextBB = (Index == (LoadCmpBlocks.size() - 1))
? EndBlock
: LoadCmpBlocks[Index + 1];
// Early exit branch if difference found to ResultBlock, otherwise continue to
// next LoadCmpBlock or EndBlock.
BranchInst *CmpBr = BranchInst::Create(ResBlock.BB, NextBB, Cmp);
Builder.Insert(CmpBr);
// Add a phi edge for the last LoadCmpBlock to Endblock with a value of 0
// since early exit to ResultBlock was not taken (no difference was found in
// any of the bytes)
if (Index == LoadCmpBlocks.size() - 1) {
Value *Zero = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 0);
PhiRes->addIncoming(Zero, LoadCmpBlocks[Index]);
}
}
// This function creates the IR intructions for loading and comparing using the
// given LoadSize. It loads the number of bytes specified by LoadSize from each
// source of the memcmp parameters. It then does a subtract to see if there was
// a difference in the loaded values. If a difference is found, it branches
// with an early exit to the ResultBlock for calculating which source was
// larger. Otherwise, it falls through to the either the next LoadCmpBlock or
// the EndBlock if this is the last LoadCmpBlock. Loading 1 byte is handled with
// a special case through emitLoadCompareByteBlock. The special handling can
// simply subtract the loaded values and add it to the result phi node.
void MemCmpExpansion::emitLoadCompareBlock(unsigned Index, int LoadSize,
int GEPIndex, bool IsLittleEndian) {
if (LoadSize == 1) {
MemCmpExpansion::emitLoadCompareByteBlock(Index, GEPIndex);
return;
}
IRBuilder<> Builder(CI->getContext());
Type *LoadSizeType = IntegerType::get(CI->getContext(), LoadSize * 8);
Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
Value *Source1 = CI->getArgOperand(0);
Value *Source2 = CI->getArgOperand(1);
Builder.SetInsertPoint(LoadCmpBlocks[Index]);
// Cast source to LoadSizeType*
if (Source1->getType() != LoadSizeType)
Source1 = Builder.CreateBitCast(Source1, LoadSizeType->getPointerTo());
if (Source2->getType() != LoadSizeType)
Source2 = Builder.CreateBitCast(Source2, LoadSizeType->getPointerTo());
// Get the base address using the GEPIndex
if (GEPIndex != 0) {
Source1 = Builder.CreateGEP(LoadSizeType, Source1,
ConstantInt::get(LoadSizeType, GEPIndex));
Source2 = Builder.CreateGEP(LoadSizeType, Source2,
ConstantInt::get(LoadSizeType, GEPIndex));
}
// Load LoadSizeType from the base address
Value *LoadSrc1 = Builder.CreateLoad(LoadSizeType, Source1);
Value *LoadSrc2 = Builder.CreateLoad(LoadSizeType, Source2);
if (IsLittleEndian) {
Function *F = LoadCmpBlocks[Index]->getParent();
Function *Bswap = Intrinsic::getDeclaration(F->getParent(),
Intrinsic::bswap, LoadSizeType);
LoadSrc1 = Builder.CreateCall(Bswap, LoadSrc1);
LoadSrc2 = Builder.CreateCall(Bswap, LoadSrc2);
}
if (LoadSizeType != MaxLoadType) {
LoadSrc1 = Builder.CreateZExtOrTrunc(LoadSrc1, MaxLoadType);
LoadSrc2 = Builder.CreateZExtOrTrunc(LoadSrc2, MaxLoadType);
}
// Add the loaded values to the phi nodes for calculating memcmp result only
// if result is not used in a zero equality.
if (!IsUsedForZeroCmp) {
ResBlock.PhiSrc1->addIncoming(LoadSrc1, LoadCmpBlocks[Index]);
ResBlock.PhiSrc2->addIncoming(LoadSrc2, LoadCmpBlocks[Index]);
}
Value *Diff = Builder.CreateSub(LoadSrc1, LoadSrc2);
Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_NE, Diff,
ConstantInt::get(Diff->getType(), 0));
BasicBlock *NextBB = (Index == (LoadCmpBlocks.size() - 1))
? EndBlock
: LoadCmpBlocks[Index + 1];
// Early exit branch if difference found to ResultBlock, otherwise continue to
// next LoadCmpBlock or EndBlock.
BranchInst *CmpBr = BranchInst::Create(ResBlock.BB, NextBB, Cmp);
Builder.Insert(CmpBr);
// Add a phi edge for the last LoadCmpBlock to Endblock with a value of 0
// since early exit to ResultBlock was not taken (no difference was found in
// any of the bytes)
if (Index == LoadCmpBlocks.size() - 1) {
Value *Zero = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 0);
PhiRes->addIncoming(Zero, LoadCmpBlocks[Index]);
}
}
// This function populates the ResultBlock with a sequence to calculate the
// memcmp result. It compares the two loaded source values and returns -1 if
// src1 < src2 and 1 if src1 > src2.
void MemCmpExpansion::emitMemCmpResultBlock(bool IsLittleEndian) {
IRBuilder<> Builder(CI->getContext());
// Special case: if memcmp result is used in a zero equality, result does not
// need to be calculated and can simply return 1.
if (IsUsedForZeroCmp) {
BasicBlock::iterator InsertPt = ResBlock.BB->getFirstInsertionPt();
Builder.SetInsertPoint(ResBlock.BB, InsertPt);
Value *Res = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 1);
PhiRes->addIncoming(Res, ResBlock.BB);
BranchInst *NewBr = BranchInst::Create(EndBlock);
Builder.Insert(NewBr);
return;
}
BasicBlock::iterator InsertPt = ResBlock.BB->getFirstInsertionPt();
Builder.SetInsertPoint(ResBlock.BB, InsertPt);
Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_ULT, ResBlock.PhiSrc1,
ResBlock.PhiSrc2);
Value *Res =
Builder.CreateSelect(Cmp, ConstantInt::get(Builder.getInt32Ty(), -1),
ConstantInt::get(Builder.getInt32Ty(), 1));
BranchInst *NewBr = BranchInst::Create(EndBlock);
Builder.Insert(NewBr);
PhiRes->addIncoming(Res, ResBlock.BB);
}
int MemCmpExpansion::calculateNumBlocks(unsigned Size) {
int NumBlocks = 0;
bool haveOneByteLoad = false;
unsigned RemainingSize = Size;
unsigned LoadSize = MaxLoadSize;
while (RemainingSize) {
if (LoadSize == 1)
haveOneByteLoad = true;
NumBlocks += RemainingSize / LoadSize;
RemainingSize = RemainingSize % LoadSize;
LoadSize = LoadSize / 2;
}
NumBlocksNonOneByte = haveOneByteLoad ? (NumBlocks - 1) : NumBlocks;
if (IsUsedForZeroCmp)
NumBlocks = NumBlocks / NumLoadsPerBlock +
(NumBlocks % NumLoadsPerBlock != 0 ? 1 : 0);
return NumBlocks;
}
void MemCmpExpansion::setupResultBlockPHINodes() {
IRBuilder<> Builder(CI->getContext());
Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
Builder.SetInsertPoint(ResBlock.BB);
ResBlock.PhiSrc1 =
Builder.CreatePHI(MaxLoadType, NumBlocksNonOneByte, "phi.src1");
ResBlock.PhiSrc2 =
Builder.CreatePHI(MaxLoadType, NumBlocksNonOneByte, "phi.src2");
}
void MemCmpExpansion::setupEndBlockPHINodes() {
IRBuilder<> Builder(CI->getContext());
Builder.SetInsertPoint(&EndBlock->front());
PhiRes = Builder.CreatePHI(Type::getInt32Ty(CI->getContext()), 2, "phi.res");
}
Value *MemCmpExpansion::getMemCmpExpansionZeroCase(unsigned Size,
bool IsLittleEndian) {
unsigned NumBytesProcessed = 0;
// This loop populates each of the LoadCmpBlocks with IR sequence to handle
// multiple loads per block
for (unsigned i = 0; i < NumBlocks; ++i) {
emitLoadCompareBlockMultipleLoads(i, Size, NumBytesProcessed);
}
emitMemCmpResultBlock(IsLittleEndian);
return PhiRes;
}
// This function expands the memcmp call into an inline expansion and returns
// the memcmp result.
Value *MemCmpExpansion::getMemCmpExpansion(bool IsLittleEndian) {
ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
uint64_t Size = SizeCast->getZExtValue();
int LoadSize = MaxLoadSize;
int NumBytesToBeProcessed = Size;
if (IsUsedForZeroCmp) {
return getMemCmpExpansionZeroCase(Size, IsLittleEndian);
}
unsigned Index = 0;
// This loop calls emitLoadCompareBlock for comparing SizeVal bytes of the two
// memcmp source. It starts with loading using the maximum load size set by
// the target. It processes any remaining bytes using a load size which is the
// next smallest power of 2.
while (NumBytesToBeProcessed) {
// Calculate how many blocks we can create with the current load size
int NumBlocks = NumBytesToBeProcessed / LoadSize;
int GEPIndex = (Size - NumBytesToBeProcessed) / LoadSize;
NumBytesToBeProcessed = NumBytesToBeProcessed % LoadSize;
// For each NumBlocks, populate the instruction sequence for loading and
// comparing LoadSize bytes
while (NumBlocks--) {
emitLoadCompareBlock(Index, LoadSize, GEPIndex, IsLittleEndian);
Index++;
GEPIndex++;
}
// Get the next LoadSize to use
LoadSize = LoadSize / 2;
}
emitMemCmpResultBlock(IsLittleEndian);
return PhiRes;
}
// This function checks to see if an expansion of memcmp can be generated.
// It checks for constant compare size that is less than the max inline size.
// If an expansion cannot occur, returns false to leave as a library call.
// Otherwise, the library call is replaced wtih new IR instruction sequence.
/// We want to transform:
/// %call = call signext i32 @memcmp(i8* %0, i8* %1, i64 15)
/// To:
/// loadbb:
/// %0 = bitcast i32* %buffer2 to i8*
/// %1 = bitcast i32* %buffer1 to i8*
/// %2 = bitcast i8* %1 to i64*
/// %3 = bitcast i8* %0 to i64*
/// %4 = load i64, i64* %2
/// %5 = load i64, i64* %3
/// %6 = call i64 @llvm.bswap.i64(i64 %4)
/// %7 = call i64 @llvm.bswap.i64(i64 %5)
/// %8 = sub i64 %6, %7
/// %9 = icmp ne i64 %8, 0
/// br i1 %9, label %res_block, label %loadbb1
/// res_block: ; preds = %loadbb2,
/// %loadbb1, %loadbb
/// %phi.src1 = phi i64 [ %6, %loadbb ], [ %22, %loadbb1 ], [ %36, %loadbb2 ]
/// %phi.src2 = phi i64 [ %7, %loadbb ], [ %23, %loadbb1 ], [ %37, %loadbb2 ]
/// %10 = icmp ult i64 %phi.src1, %phi.src2
/// %11 = select i1 %10, i32 -1, i32 1
/// br label %endblock
/// loadbb1: ; preds = %loadbb
/// %12 = bitcast i32* %buffer2 to i8*
/// %13 = bitcast i32* %buffer1 to i8*
/// %14 = bitcast i8* %13 to i32*
/// %15 = bitcast i8* %12 to i32*
/// %16 = getelementptr i32, i32* %14, i32 2
/// %17 = getelementptr i32, i32* %15, i32 2
/// %18 = load i32, i32* %16
/// %19 = load i32, i32* %17
/// %20 = call i32 @llvm.bswap.i32(i32 %18)
/// %21 = call i32 @llvm.bswap.i32(i32 %19)
/// %22 = zext i32 %20 to i64
/// %23 = zext i32 %21 to i64
/// %24 = sub i64 %22, %23
/// %25 = icmp ne i64 %24, 0
/// br i1 %25, label %res_block, label %loadbb2
/// loadbb2: ; preds = %loadbb1
/// %26 = bitcast i32* %buffer2 to i8*
/// %27 = bitcast i32* %buffer1 to i8*
/// %28 = bitcast i8* %27 to i16*
/// %29 = bitcast i8* %26 to i16*
/// %30 = getelementptr i16, i16* %28, i16 6
/// %31 = getelementptr i16, i16* %29, i16 6
/// %32 = load i16, i16* %30
/// %33 = load i16, i16* %31
/// %34 = call i16 @llvm.bswap.i16(i16 %32)
/// %35 = call i16 @llvm.bswap.i16(i16 %33)
/// %36 = zext i16 %34 to i64
/// %37 = zext i16 %35 to i64
/// %38 = sub i64 %36, %37
/// %39 = icmp ne i64 %38, 0
/// br i1 %39, label %res_block, label %loadbb3
/// loadbb3: ; preds = %loadbb2
/// %40 = bitcast i32* %buffer2 to i8*
/// %41 = bitcast i32* %buffer1 to i8*
/// %42 = getelementptr i8, i8* %41, i8 14
/// %43 = getelementptr i8, i8* %40, i8 14
/// %44 = load i8, i8* %42
/// %45 = load i8, i8* %43
/// %46 = zext i8 %44 to i32
/// %47 = zext i8 %45 to i32
/// %48 = sub i32 %46, %47
/// br label %endblock
/// endblock: ; preds = %res_block,
/// %loadbb3
/// %phi.res = phi i32 [ %48, %loadbb3 ], [ %11, %res_block ]
/// ret i32 %phi.res
static bool expandMemCmp(CallInst *CI, const TargetTransformInfo *TTI,
const TargetLowering *TLI, const DataLayout *DL) {
NumMemCmpCalls++;
IRBuilder<> Builder(CI->getContext());
// TTI call to check if target would like to expand memcmp and get the
// MaxLoadSize
unsigned MaxLoadSize;
if (!TTI->expandMemCmp(CI, MaxLoadSize))
return false;
// Early exit from expansion if -Oz
if (CI->getParent()->getParent()->optForMinSize()) {
return false;
}
// Early exit from expansion if size is not a constant
ConstantInt *SizeCast = dyn_cast<ConstantInt>(CI->getArgOperand(2));
if (!SizeCast) {
NumMemCmpNotConstant++;
return false;
}
// Early exit from expansion if size greater than max bytes to load
uint64_t SizeVal = SizeCast->getZExtValue();
unsigned NumLoads = 0;
unsigned RemainingSize = SizeVal;
unsigned LoadSize = MaxLoadSize;
while (RemainingSize) {
NumLoads += RemainingSize / LoadSize;
RemainingSize = RemainingSize % LoadSize;
LoadSize = LoadSize / 2;
}
if (NumLoads >
TLI->getMaxExpandSizeMemcmp(CI->getParent()->getParent()->optForSize())) {
NumMemCmpGreaterThanMax++;
return false;
}
NumMemCmpInlined++;
// MemCmpHelper object, creates and sets up basic blocks required for
// expanding memcmp with size SizeVal
unsigned NumLoadsPerBlock = MemCmpNumLoadsPerBlock;
MemCmpExpansion MemCmpHelper(CI, MaxLoadSize, NumLoadsPerBlock);
Value *Res = MemCmpHelper.getMemCmpExpansion(DL->isLittleEndian());
// Replace call with result of expansion and erarse call.
CI->replaceAllUsesWith(Res);
CI->eraseFromParent();
return true;
}
bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
BasicBlock *BB = CI->getParent();
@ -1780,6 +2380,15 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
CI->eraseFromParent();
return true;
}
LibFunc Func;
if (TLInfo->getLibFunc(*CI->getCalledFunction(), Func) &&
Func == LibFunc_memcmp) {
if (expandMemCmp(CI, TTI, TLI, DL)) {
ModifiedDT = true;
return true;
}
}
return false;
}
@ -4927,6 +5536,7 @@ bool CodeGenPrepare::optimizeSwitchInst(SwitchInst *SI) {
return true;
}
namespace {
/// \brief Helper class to promote a scalar operation to a vector one.
/// This class is used to move downward extractelement transition.

View File

@ -74,7 +74,7 @@ void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
++I) {
unsigned Reg = *I;
if (!IsReturnBlock && !(Pristine.test(Reg) || BB->isLiveIn(Reg)))
if (!IsReturnBlock && !Pristine.test(Reg))
continue;
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) {
unsigned Reg = *AI;

View File

@ -98,12 +98,10 @@ bool Localizer::runOnMachineFunction(MachineFunction &MF) {
// Create the localized instruction.
MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
LocalizedInstrs.insert(LocalizedMI);
// Move it at the right place.
MachineInstr &MIUse = *MOUse.getParent();
if (MIUse.getParent() == InsertMBB)
InsertMBB->insert(MIUse, LocalizedMI);
else
InsertMBB->insert(InsertMBB->getFirstNonPHI(), LocalizedMI);
// Don't try to be smart for the insertion point.
// There is no guarantee that the first seen use is the first
// use in the block.
InsertMBB->insert(InsertMBB->getFirstNonPHI(), LocalizedMI);
// Set a new register for the definition.
unsigned NewReg =

View File

@ -607,8 +607,20 @@ MachineInstr *ImplicitNullChecks::insertFaultingInstr(
.addMBB(HandlerMBB)
.addImm(MI->getOpcode());
for (auto &MO : MI->uses())
MIB.add(MO);
for (auto &MO : MI->uses()) {
if (MO.isReg()) {
MachineOperand NewMO = MO;
if (MO.isUse()) {
NewMO.setIsKill(false);
} else {
assert(MO.isDef() && "Expected def or use");
NewMO.setIsDead(false);
}
MIB.add(NewMO);
} else {
MIB.add(MO);
}
}
MIB.setMemRefs(MI->memoperands_begin(), MI->memoperands_end());

View File

@ -0,0 +1,231 @@
//===-- LiveRangeShrink.cpp - Move instructions to shrink live range ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
///===---------------------------------------------------------------------===//
///
/// \file
/// This pass moves instructions close to the definition of its operands to
/// shrink live range of the def instruction. The code motion is limited within
/// the basic block. The moved instruction should have 1 def, and more than one
/// uses, all of which are the only use of the def.
///
///===---------------------------------------------------------------------===//
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "lrshrink"
STATISTIC(NumInstrsHoistedToShrinkLiveRange,
"Number of insructions hoisted to shrink live range.");
using namespace llvm;
namespace {
class LiveRangeShrink : public MachineFunctionPass {
public:
static char ID;
LiveRangeShrink() : MachineFunctionPass(ID) {
initializeLiveRangeShrinkPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
StringRef getPassName() const override { return "Live Range Shrink"; }
bool runOnMachineFunction(MachineFunction &MF) override;
};
} // End anonymous namespace.
char LiveRangeShrink::ID = 0;
char &llvm::LiveRangeShrinkID = LiveRangeShrink::ID;
INITIALIZE_PASS(LiveRangeShrink, "lrshrink", "Live Range Shrink Pass", false,
false)
namespace {
typedef DenseMap<MachineInstr *, unsigned> InstOrderMap;
/// Returns \p New if it's dominated by \p Old, otherwise return \p Old.
/// \p M maintains a map from instruction to its dominating order that satisfies
/// M[A] > M[B] guarantees that A is dominated by B.
/// If \p New is not in \p M, return \p Old. Otherwise if \p Old is null, return
/// \p New.
MachineInstr *FindDominatedInstruction(MachineInstr &New, MachineInstr *Old,
const InstOrderMap &M) {
auto NewIter = M.find(&New);
if (NewIter == M.end())
return Old;
if (Old == nullptr)
return &New;
unsigned OrderOld = M.find(Old)->second;
unsigned OrderNew = NewIter->second;
if (OrderOld != OrderNew)
return OrderOld < OrderNew ? &New : Old;
// OrderOld == OrderNew, we need to iterate down from Old to see if it
// can reach New, if yes, New is dominated by Old.
for (MachineInstr *I = Old->getNextNode(); M.find(I)->second == OrderNew;
I = I->getNextNode())
if (I == &New)
return &New;
return Old;
}
/// Builds Instruction to its dominating order number map \p M by traversing
/// from instruction \p Start.
void BuildInstOrderMap(MachineBasicBlock::iterator Start, InstOrderMap &M) {
M.clear();
unsigned i = 0;
for (MachineInstr &I : make_range(Start, Start->getParent()->end()))
M[&I] = i++;
}
} // end anonymous namespace
bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()))
return false;
MachineRegisterInfo &MRI = MF.getRegInfo();
DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
InstOrderMap IOM;
// Map from register to instruction order (value of IOM) where the
// register is used last. When moving instructions up, we need to
// make sure all its defs (including dead def) will not cross its
// last use when moving up.
DenseMap<unsigned, std::pair<unsigned, MachineInstr *>> UseMap;
for (MachineBasicBlock &MBB : MF) {
if (MBB.empty())
continue;
bool SawStore = false;
BuildInstOrderMap(MBB.begin(), IOM);
UseMap.clear();
for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
MachineInstr &MI = *Next;
++Next;
if (MI.isPHI() || MI.isDebugValue())
continue;
if (MI.mayStore())
SawStore = true;
unsigned CurrentOrder = IOM[&MI];
unsigned Barrier = 0;
MachineInstr *BarrierMI = nullptr;
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || MO.isDebug())
continue;
if (MO.isUse())
UseMap[MO.getReg()] = std::make_pair(CurrentOrder, &MI);
else if (MO.isDead() && UseMap.count(MO.getReg()))
// Barrier is the last instruction where MO get used. MI should not
// be moved above Barrier.
if (Barrier < UseMap[MO.getReg()].first) {
Barrier = UseMap[MO.getReg()].first;
BarrierMI = UseMap[MO.getReg()].second;
}
}
if (!MI.isSafeToMove(nullptr, SawStore)) {
// If MI has side effects, it should become a barrier for code motion.
// IOM is rebuild from the next instruction to prevent later
// instructions from being moved before this MI.
if (MI.hasUnmodeledSideEffects() && Next != MBB.end()) {
BuildInstOrderMap(Next, IOM);
SawStore = false;
}
continue;
}
const MachineOperand *DefMO = nullptr;
MachineInstr *Insert = nullptr;
// Number of live-ranges that will be shortened. We do not count
// live-ranges that are defined by a COPY as it could be coalesced later.
unsigned NumEligibleUse = 0;
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || MO.isDead() || MO.isDebug())
continue;
unsigned Reg = MO.getReg();
// Do not move the instruction if it def/uses a physical register,
// unless it is a constant physical register or a noreg.
if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
if (!Reg || MRI.isConstantPhysReg(Reg))
continue;
Insert = nullptr;
break;
}
if (MO.isDef()) {
// Do not move if there is more than one def.
if (DefMO) {
Insert = nullptr;
break;
}
DefMO = &MO;
} else if (MRI.hasOneNonDBGUse(Reg) && MRI.hasOneDef(Reg) && DefMO &&
MRI.getRegClass(DefMO->getReg()) ==
MRI.getRegClass(MO.getReg())) {
// The heuristic does not handle different register classes yet
// (registers of different sizes, looser/tighter constraints). This
// is because it needs more accurate model to handle register
// pressure correctly.
MachineInstr &DefInstr = *MRI.def_instr_begin(Reg);
if (!DefInstr.isCopy())
NumEligibleUse++;
Insert = FindDominatedInstruction(DefInstr, Insert, IOM);
} else {
Insert = nullptr;
break;
}
}
// If Barrier equals IOM[I], traverse forward to find if BarrierMI is
// after Insert, if yes, then we should not hoist.
for (MachineInstr *I = Insert; I && IOM[I] == Barrier;
I = I->getNextNode())
if (I == BarrierMI) {
Insert = nullptr;
break;
}
// Move the instruction when # of shrunk live range > 1.
if (DefMO && Insert && NumEligibleUse > 1 && Barrier <= IOM[Insert]) {
MachineBasicBlock::iterator I = std::next(Insert->getIterator());
// Skip all the PHI and debug instructions.
while (I != MBB.end() && (I->isPHI() || I->isDebugValue()))
I = std::next(I);
if (I == MI.getIterator())
continue;
// Update the dominator order to be the same as the insertion point.
// We do this to maintain a non-decreasing order without need to update
// all instruction orders after the insertion point.
unsigned NewOrder = IOM[&*I];
IOM[&MI] = NewOrder;
NumInstrsHoistedToShrinkLiveRange++;
// Find MI's debug value following MI.
MachineBasicBlock::iterator EndIter = std::next(MI.getIterator());
if (MI.getOperand(0).isReg())
for (; EndIter != MBB.end() && EndIter->isDebugValue() &&
EndIter->getOperand(0).isReg() &&
EndIter->getOperand(0).getReg() == MI.getOperand(0).getReg();
++EndIter, ++Next)
IOM[&*EndIter] = NewOrder;
MBB.splice(I, &MBB, MI.getIterator(), EndIter);
}
}
}
return false;
}

View File

@ -332,8 +332,6 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
if (YamlMF.NoVRegs)
MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
if (YamlMF.Legalized)
MF.getProperties().set(MachineFunctionProperties::Property::Legalized);
if (YamlMF.RegBankSelected)

View File

@ -183,8 +183,6 @@ void MIRPrinter::print(const MachineFunction &MF) {
YamlMF.Alignment = MF.getAlignment();
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
YamlMF.NoVRegs = MF.getProperties().hasProperty(
MachineFunctionProperties::Property::NoVRegs);
YamlMF.Legalized = MF.getProperties().hasProperty(
MachineFunctionProperties::Property::Legalized);
YamlMF.RegBankSelected = MF.getProperties().hasProperty(

View File

@ -350,6 +350,13 @@ void MachineBasicBlock::removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) {
LiveIns.erase(I);
}
MachineBasicBlock::livein_iterator
MachineBasicBlock::removeLiveIn(MachineBasicBlock::livein_iterator I) {
// Get non-const version of iterator.
LiveInVector::iterator LI = LiveIns.begin() + (I - LiveIns.begin());
return LiveIns.erase(LI);
}
bool MachineBasicBlock::isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) const {
livein_iterator I = find_if(
LiveIns, [Reg](const RegisterMaskPair &LI) { return LI.PhysReg == Reg; });

View File

@ -1,4 +1,4 @@
//===-- lib/CodeGen/MachineInstr.cpp --------------------------------------===//
//===- lib/CodeGen/MachineInstr.cpp ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -11,21 +11,34 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
@ -35,9 +48,13 @@
#include "llvm/IR/Value.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LowLevelTypeImpl.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
@ -45,6 +62,14 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <utility>
using namespace llvm;
static cl::opt<bool> PrintWholeRegMask(
@ -256,7 +281,7 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
case MachineOperand::MO_GlobalAddress:
return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset();
case MachineOperand::MO_ExternalSymbol:
return !strcmp(getSymbolName(), Other.getSymbolName()) &&
return strcmp(getSymbolName(), Other.getSymbolName()) == 0 &&
getOffset() == Other.getOffset();
case MachineOperand::MO_BlockAddress:
return getBlockAddress() == Other.getBlockAddress() &&
@ -723,9 +748,7 @@ void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) {
/// the MCInstrDesc.
MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
DebugLoc dl, bool NoImp)
: MCID(&tid), Parent(nullptr), Operands(nullptr), NumOperands(0), Flags(0),
AsmPrinterFlags(0), NumMemRefs(0), MemRefs(nullptr),
debugLoc(std::move(dl)) {
: MCID(&tid), debugLoc(std::move(dl)) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
// Reserve space for the expected number of operands.
@ -742,9 +765,8 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
/// MachineInstr ctor - Copies MachineInstr arg exactly
///
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
: MCID(&MI.getDesc()), Parent(nullptr), Operands(nullptr), NumOperands(0),
Flags(0), AsmPrinterFlags(0), NumMemRefs(MI.NumMemRefs),
MemRefs(MI.MemRefs), debugLoc(MI.getDebugLoc()) {
: MCID(&MI.getDesc()), NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
debugLoc(MI.getDebugLoc()) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
CapOperands = OperandCapacity::get(MI.getNumOperands());
@ -1633,8 +1655,8 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other,
// memory objects. It can save compile time, and possibly catch some
// corner cases not currently covered.
assert ((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset");
assert ((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset");
assert((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset");
assert((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset");
int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset());
int64_t Overlapa = MMOa->getSize() + MMOa->getOffset() - MinOffset;
@ -1667,7 +1689,7 @@ bool MachineInstr::hasOrderedMemoryRef() const {
return true;
// Check if any of our memory operands are ordered.
return any_of(memoperands(), [](const MachineMemOperand *MMO) {
return llvm::any_of(memoperands(), [](const MachineMemOperand *MMO) {
return !MMO->isUnordered();
});
}
@ -1841,7 +1863,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
return;
// Print the rest of the operands.
bool OmittedAnyCallClobbers = false;
bool FirstOp = true;
unsigned AsmDescOp = ~0u;
unsigned AsmOpCount = 0;
@ -1878,31 +1899,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
VirtRegs.push_back(MO.getReg());
// Omit call-clobbered registers which aren't used anywhere. This makes
// call instructions much less noisy on targets where calls clobber lots
// of registers. Don't rely on MO.isDead() because we may be called before
// LiveVariables is run, or we may be looking at a non-allocatable reg.
if (MRI && isCall() &&
MO.isReg() && MO.isImplicit() && MO.isDef()) {
unsigned Reg = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
if (MRI->use_empty(Reg)) {
bool HasAliasLive = false;
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
unsigned AliasReg = *AI;
if (!MRI->use_empty(AliasReg)) {
HasAliasLive = true;
break;
}
}
if (!HasAliasLive) {
OmittedAnyCallClobbers = true;
continue;
}
}
}
}
if (FirstOp) FirstOp = false; else OS << ",";
OS << " ";
if (i < getDesc().NumOperands) {
@ -1984,12 +1980,6 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
MO.print(OS, MST, TRI);
}
// Briefly indicate whether any call clobbers were omitted.
if (OmittedAnyCallClobbers) {
if (!FirstOp) OS << ",";
OS << " ...";
}
bool HaveSemi = false;
const unsigned PrintableFlags = FrameSetup | FrameDestroy;
if (Flags & PrintableFlags) {
@ -2255,8 +2245,8 @@ void MachineInstr::setPhysRegsDeadExcept(ArrayRef<unsigned> UsedRegs,
unsigned Reg = MO.getReg();
if (!TargetRegisterInfo::isPhysicalRegister(Reg)) continue;
// If there are no uses, including partial uses, the def is dead.
if (none_of(UsedRegs,
[&](unsigned Use) { return TRI.regsOverlap(Use, Reg); }))
if (llvm::none_of(UsedRegs,
[&](unsigned Use) { return TRI.regsOverlap(Use, Reg); }))
MO.setIsDead();
}

View File

@ -7,27 +7,34 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionInitializer.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <utility>
#include <vector>
using namespace llvm;
using namespace llvm::dwarf;
@ -37,14 +44,16 @@ INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo",
char MachineModuleInfo::ID = 0;
// Out of line virtual method.
MachineModuleInfoImpl::~MachineModuleInfoImpl() {}
MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
namespace llvm {
class MMIAddrLabelMapCallbackPtr final : CallbackVH {
MMIAddrLabelMap *Map;
MMIAddrLabelMap *Map = nullptr;
public:
MMIAddrLabelMapCallbackPtr() : Map(nullptr) {}
MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V), Map(nullptr) {}
MMIAddrLabelMapCallbackPtr() = default;
MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V) {}
void setPtr(BasicBlock *BB) {
ValueHandleBase::operator=(BB);
@ -75,11 +84,12 @@ class MMIAddrLabelMap {
/// This is a per-function list of symbols whose corresponding BasicBlock got
/// deleted. These symbols need to be emitted at some point in the file, so
/// AsmPrinter emits them after the function body.
DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >
DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>
DeletedAddrLabelsNeedingEmission;
public:
public:
MMIAddrLabelMap(MCContext &context) : Context(context) {}
~MMIAddrLabelMap() {
assert(DeletedAddrLabelsNeedingEmission.empty() &&
"Some labels for deleted blocks never got emitted");
@ -93,7 +103,8 @@ class MMIAddrLabelMap {
void UpdateForDeletedBlock(BasicBlock *BB);
void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New);
};
}
} // end namespace llvm
ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
assert(BB->hasAddressTaken() &&
@ -119,7 +130,7 @@ ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
/// If we have any deleted symbols for F, return them.
void MMIAddrLabelMap::
takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >::iterator I =
DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>::iterator I =
DeletedAddrLabelsNeedingEmission.find(F);
// If there are no entries for the function, just return.
@ -130,7 +141,6 @@ takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
DeletedAddrLabelsNeedingEmission.erase(I);
}
void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
// If the block got deleted, there is no need for the symbol. If the symbol
// was already emitted, we can just forget about it, otherwise we need to
@ -177,7 +187,6 @@ void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
OldEntry.Symbols.end());
}
void MMIAddrLabelMapCallbackPtr::deleted() {
Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr()));
}
@ -186,9 +195,6 @@ void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) {
Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2));
}
//===----------------------------------------------------------------------===//
MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM)
: ImmutablePass(ID), TM(*TM),
Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(),
@ -196,11 +202,9 @@ MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM)
initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry());
}
MachineModuleInfo::~MachineModuleInfo() {
}
MachineModuleInfo::~MachineModuleInfo() = default;
bool MachineModuleInfo::doInitialization(Module &M) {
ObjFileMMI = nullptr;
CurCallSite = 0;
DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
@ -211,7 +215,6 @@ bool MachineModuleInfo::doInitialization(Module &M) {
}
bool MachineModuleInfo::doFinalization(Module &M) {
Personalities.clear();
delete AddrLabelSymbols;
@ -290,10 +293,12 @@ void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
}
namespace {
/// This pass frees the MachineFunction object associated with a Function.
class FreeMachineFunction : public FunctionPass {
public:
static char ID;
FreeMachineFunction() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
@ -311,14 +316,14 @@ class FreeMachineFunction : public FunctionPass {
return "Free MachineFunction";
}
};
char FreeMachineFunction::ID;
} // end anonymous namespace
namespace llvm {
FunctionPass *createFreeMachineFunctionPass() {
char FreeMachineFunction::ID;
FunctionPass *llvm::createFreeMachineFunctionPass() {
return new FreeMachineFunction();
}
} // end namespace llvm
//===- MMI building helpers -----------------------------------------------===//

View File

@ -280,6 +280,7 @@ namespace {
SDValue visitSELECT_CC(SDNode *N);
SDValue visitSETCC(SDNode *N);
SDValue visitSETCCE(SDNode *N);
SDValue visitSETCCCARRY(SDNode *N);
SDValue visitSIGN_EXTEND(SDNode *N);
SDValue visitZERO_EXTEND(SDNode *N);
SDValue visitANY_EXTEND(SDNode *N);
@ -1457,6 +1458,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::SELECT_CC: return visitSELECT_CC(N);
case ISD::SETCC: return visitSETCC(N);
case ISD::SETCCE: return visitSETCCE(N);
case ISD::SETCCCARRY: return visitSETCCCARRY(N);
case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N);
case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N);
case ISD::ANY_EXTEND: return visitANY_EXTEND(N);
@ -1958,7 +1960,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
// fold (a+b) -> (a|b) iff a and b share no bits.
if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) &&
VT.isInteger() && DAG.haveNoCommonBitsSet(N0, N1))
DAG.haveNoCommonBitsSet(N0, N1))
return DAG.getNode(ISD::OR, DL, VT, N0, N1);
if (SDValue Combined = visitADDLike(N0, N1, N))
@ -1970,6 +1972,44 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
return SDValue();
}
static SDValue getAsCarry(const TargetLowering &TLI, SDValue V) {
bool Masked = false;
// First, peel away TRUNCATE/ZERO_EXTEND/AND nodes due to legalization.
while (true) {
if (V.getOpcode() == ISD::TRUNCATE || V.getOpcode() == ISD::ZERO_EXTEND) {
V = V.getOperand(0);
continue;
}
if (V.getOpcode() == ISD::AND && isOneConstant(V.getOperand(1))) {
Masked = true;
V = V.getOperand(0);
continue;
}
break;
}
// If this is not a carry, return.
if (V.getResNo() != 1)
return SDValue();
if (V.getOpcode() != ISD::ADDCARRY && V.getOpcode() != ISD::SUBCARRY &&
V.getOpcode() != ISD::UADDO && V.getOpcode() != ISD::USUBO)
return SDValue();
// If the result is masked, then no matter what kind of bool it is we can
// return. If it isn't, then we need to make sure the bool type is either 0 or
// 1 and not other values.
if (Masked ||
TLI.getBooleanContents(V.getValueType()) ==
TargetLoweringBase::ZeroOrOneBooleanContent)
return V;
return SDValue();
}
SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference) {
EVT VT = N0.getValueType();
SDLoc DL(LocReference);
@ -2017,6 +2057,13 @@ SDValue DAGCombiner::visitADDLike(SDValue N0, SDValue N1, SDNode *LocReference)
return DAG.getNode(ISD::ADDCARRY, DL, N1->getVTList(),
N0, N1.getOperand(0), N1.getOperand(2));
// (add X, Carry) -> (addcarry X, 0, Carry)
if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT))
if (SDValue Carry = getAsCarry(TLI, N1))
return DAG.getNode(ISD::ADDCARRY, DL,
DAG.getVTList(VT, Carry.getValueType()), N0,
DAG.getConstant(0, DL, VT), Carry);
return SDValue();
}
@ -2090,6 +2137,8 @@ SDValue DAGCombiner::visitUADDO(SDNode *N) {
}
SDValue DAGCombiner::visitUADDOLike(SDValue N0, SDValue N1, SDNode *N) {
auto VT = N0.getValueType();
// (uaddo X, (addcarry Y, 0, Carry)) -> (addcarry X, Y, Carry)
// If Y + 1 cannot overflow.
if (N1.getOpcode() == ISD::ADDCARRY && isNullConstant(N1.getOperand(1))) {
@ -2100,6 +2149,12 @@ SDValue DAGCombiner::visitUADDOLike(SDValue N0, SDValue N1, SDNode *N) {
N1.getOperand(2));
}
// (uaddo X, Carry) -> (addcarry X, 0, Carry)
if (TLI.isOperationLegalOrCustom(ISD::ADDCARRY, VT))
if (SDValue Carry = getAsCarry(TLI, N1))
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0,
DAG.getConstant(0, SDLoc(N), VT), Carry);
return SDValue();
}
@ -2167,6 +2222,41 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(),
N0.getOperand(0), N0.getOperand(1), CarryIn);
/**
* When one of the addcarry argument is itself a carry, we may be facing
* a diamond carry propagation. In which case we try to transform the DAG
* to ensure linear carry propagation if that is possible.
*
* We are trying to get:
* (addcarry X, 0, (addcarry A, B, Z):Carry)
*/
if (auto Y = getAsCarry(TLI, N1)) {
/**
* (uaddo A, B)
* / \
* Carry Sum
* | \
* | (addcarry *, 0, Z)
* | /
* \ Carry
* | /
* (addcarry X, *, *)
*/
if (Y.getOpcode() == ISD::UADDO &&
CarryIn.getResNo() == 1 &&
CarryIn.getOpcode() == ISD::ADDCARRY &&
isNullConstant(CarryIn.getOperand(1)) &&
CarryIn.getOperand(0) == Y.getValue(0)) {
auto NewY = DAG.getNode(ISD::ADDCARRY, SDLoc(N), Y->getVTList(),
Y.getOperand(0), Y.getOperand(1),
CarryIn.getOperand(2));
AddToWorklist(NewY.getNode());
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0,
DAG.getConstant(0, SDLoc(N), N0.getValueType()),
NewY.getValue(1));
}
}
return SDValue();
}
@ -6754,6 +6844,19 @@ SDValue DAGCombiner::visitSETCCE(SDNode *N) {
return SDValue();
}
SDValue DAGCombiner::visitSETCCCARRY(SDNode *N) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
SDValue Carry = N->getOperand(2);
SDValue Cond = N->getOperand(3);
// If Carry is false, fold to a regular SETCC.
if (isNullConstant(Carry))
return DAG.getNode(ISD::SETCC, SDLoc(N), N->getVTList(), LHS, RHS, Cond);
return SDValue();
}
/// Try to fold a sext/zext/aext dag node into a ConstantSDNode or
/// a build_vector of constants.
/// This function is called by the DAGCombiner when visiting sext/zext/aext
@ -7124,12 +7227,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, DL, VT, LN0->getChain(),
LN0->getBasePtr(), N0.getValueType(),
LN0->getMemOperand());
CombineTo(N, ExtLoad);
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SDLoc(N0),
N0.getValueType(), ExtLoad);
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::SIGN_EXTEND);
return SDValue(N, 0); // Return N so it doesn't get rechecked!
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
return CombineTo(N, ExtLoad); // Return N so it doesn't get rechecked!
}
}
@ -7185,10 +7287,9 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE,
SDLoc(N0.getOperand(0)),
N0.getOperand(0).getValueType(), ExtLoad);
CombineTo(N, And);
CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::SIGN_EXTEND);
return SDValue(N, 0); // Return N so it doesn't get rechecked!
CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
return CombineTo(N, And); // Return N so it doesn't get rechecked!
}
}
}
@ -7427,12 +7528,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SDLoc(N0),
N0.getValueType(), ExtLoad);
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, SDLoc(N), ISD::ZERO_EXTEND);
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, SDLoc(N),
ISD::ZERO_EXTEND);
CombineTo(N, ExtLoad);
return SDValue(N, 0); // Return N so it doesn't get rechecked!
return CombineTo(N, ExtLoad); // Return N so it doesn't get rechecked!
}
}
@ -7482,11 +7580,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDValue Trunc = DAG.getNode(ISD::TRUNCATE,
SDLoc(N0.getOperand(0)),
N0.getOperand(0).getValueType(), ExtLoad);
CombineTo(N, And);
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL, ISD::ZERO_EXTEND);
CombineTo(N0.getOperand(0).getNode(), Trunc, ExtLoad.getValue(1));
ExtendSetCCUses(SetCCs, Trunc, ExtLoad, DL,
ISD::ZERO_EXTEND);
return SDValue(N, 0); // Return N so it doesn't get rechecked!
return CombineTo(N, And); // Return N so it doesn't get rechecked!
}
}
}
@ -12777,10 +12873,10 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
}
// If we have load/store pair instructions and we only have two values,
// don't bother.
// don't bother merging.
unsigned RequiredAlignment;
if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
St->getAlignment() >= RequiredAlignment) {
StoreNodes[0].MemNode->getAlignment() >= RequiredAlignment) {
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
continue;
}

View File

@ -2875,6 +2875,7 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
case ISD::SETCCE: Res = ExpandIntOp_SETCCE(N); break;
case ISD::SETCCCARRY: Res = ExpandIntOp_SETCCCARRY(N); break;
case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break;
case ISD::STORE: Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo); break;
case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
@ -3009,14 +3010,16 @@ void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS,
return;
}
// Lower with SETCCE if the target supports it.
// Lower with SETCCE or SETCCCARRY if the target supports it.
EVT HiVT = LHSHi.getValueType();
EVT ExpandVT = TLI.getTypeToExpandTo(*DAG.getContext(), HiVT);
bool HasSETCCCARRY = TLI.isOperationLegalOrCustom(ISD::SETCCCARRY, ExpandVT);
// FIXME: Make all targets support this, then remove the other lowering.
if (TLI.getOperationAction(
ISD::SETCCE,
TLI.getTypeToExpandTo(*DAG.getContext(), LHSLo.getValueType())) ==
TargetLowering::Custom) {
// SETCCE can detect < and >= directly. For > and <=, flip operands and
// condition code.
if (HasSETCCCARRY ||
TLI.getOperationAction(ISD::SETCCE, ExpandVT) == TargetLowering::Custom) {
// SETCCE/SETCCCARRY can detect < and >= directly. For > and <=, flip
// operands and condition code.
bool FlipOperands = false;
switch (CCCode) {
case ISD::SETGT: CCCode = ISD::SETLT; FlipOperands = true; break;
@ -3030,27 +3033,28 @@ void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS,
std::swap(LHSHi, RHSHi);
}
// Perform a wide subtraction, feeding the carry from the low part into
// SETCCE. The SETCCE operation is essentially looking at the high part of
// the result of LHS - RHS. It is negative iff LHS < RHS. It is zero or
// positive iff LHS >= RHS.
SDVTList VTList = DAG.getVTList(LHSLo.getValueType(), MVT::Glue);
SDValue LowCmp = DAG.getNode(ISD::SUBC, dl, VTList, LHSLo, RHSLo);
SDValue Res =
DAG.getNode(ISD::SETCCE, dl, getSetCCResultType(LHSLo.getValueType()),
LHSHi, RHSHi, LowCmp.getValue(1), DAG.getCondCode(CCCode));
// SETCCE/SETCCCARRY. The SETCCE/SETCCCARRY operation is essentially
// looking at the high part of the result of LHS - RHS. It is negative
// iff LHS < RHS. It is zero or positive iff LHS >= RHS.
EVT LoVT = LHSLo.getValueType();
SDVTList VTList = DAG.getVTList(
LoVT, HasSETCCCARRY ? getSetCCResultType(LoVT) : MVT::Glue);
SDValue LowCmp = DAG.getNode(HasSETCCCARRY ? ISD::USUBO : ISD::SUBC, dl,
VTList, LHSLo, RHSLo);
SDValue Res = DAG.getNode(HasSETCCCARRY ? ISD::SETCCCARRY : ISD::SETCCE, dl,
getSetCCResultType(HiVT), LHSHi, RHSHi,
LowCmp.getValue(1), DAG.getCondCode(CCCode));
NewLHS = Res;
NewRHS = SDValue();
return;
}
NewLHS = TLI.SimplifySetCC(getSetCCResultType(LHSHi.getValueType()),
LHSHi, RHSHi, ISD::SETEQ, false,
DagCombineInfo, dl);
NewLHS = TLI.SimplifySetCC(getSetCCResultType(HiVT), LHSHi, RHSHi, ISD::SETEQ,
false, DagCombineInfo, dl);
if (!NewLHS.getNode())
NewLHS = DAG.getSetCC(dl, getSetCCResultType(LHSHi.getValueType()),
LHSHi, RHSHi, ISD::SETEQ);
NewLHS = DAG.getSelect(dl, LoCmp.getValueType(),
NewLHS, LoCmp, HiCmp);
NewLHS =
DAG.getSetCC(dl, getSetCCResultType(HiVT), LHSHi, RHSHi, ISD::SETEQ);
NewLHS = DAG.getSelect(dl, LoCmp.getValueType(), NewLHS, LoCmp, HiCmp);
NewRHS = SDValue();
}
@ -3103,8 +3107,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) {
}
// Otherwise, update N to have the operands specified.
return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
DAG.getCondCode(CCCode)), 0);
return SDValue(
DAG.UpdateNodeOperands(N, NewLHS, NewRHS, DAG.getCondCode(CCCode)), 0);
}
SDValue DAGTypeLegalizer::ExpandIntOp_SETCCE(SDNode *N) {
@ -3125,6 +3129,24 @@ SDValue DAGTypeLegalizer::ExpandIntOp_SETCCE(SDNode *N) {
LowCmp.getValue(1), Cond);
}
SDValue DAGTypeLegalizer::ExpandIntOp_SETCCCARRY(SDNode *N) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
SDValue Carry = N->getOperand(2);
SDValue Cond = N->getOperand(3);
SDLoc dl = SDLoc(N);
SDValue LHSLo, LHSHi, RHSLo, RHSHi;
GetExpandedInteger(LHS, LHSLo, LHSHi);
GetExpandedInteger(RHS, RHSLo, RHSHi);
// Expand to a SUBE for the low part and a smaller SETCCCARRY for the high.
SDVTList VTList = DAG.getVTList(LHSLo.getValueType(), Carry.getValueType());
SDValue LowCmp = DAG.getNode(ISD::SUBCARRY, dl, VTList, LHSLo, RHSLo, Carry);
return DAG.getNode(ISD::SETCCCARRY, dl, N->getValueType(0), LHSHi, RHSHi,
LowCmp.getValue(1), Cond);
}
SDValue DAGTypeLegalizer::ExpandIntOp_Shift(SDNode *N) {
// The value being shifted is legal, but the shift amount is too big.
// It follows that either the result of the shift is undefined, or the

View File

@ -381,6 +381,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue ExpandIntOp_SELECT_CC(SDNode *N);
SDValue ExpandIntOp_SETCC(SDNode *N);
SDValue ExpandIntOp_SETCCE(SDNode *N);
SDValue ExpandIntOp_SETCCCARRY(SDNode *N);
SDValue ExpandIntOp_Shift(SDNode *N);
SDValue ExpandIntOp_SINT_TO_FP(SDNode *N);
SDValue ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo);

View File

@ -226,6 +226,7 @@ class ScheduleDAGRRList : public ScheduleDAGSDNodes {
void UnscheduleNodeBottomUp(SUnit*);
void RestoreHazardCheckerBottomUp();
void BacktrackBottomUp(SUnit*, SUnit*);
SUnit *TryUnfoldSU(SUnit *);
SUnit *CopyAndMoveSuccessors(SUnit*);
void InsertCopiesAndMoveSuccs(SUnit*, unsigned,
const TargetRegisterClass*,
@ -780,7 +781,7 @@ void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
}
/// CapturePred - This does the opposite of ReleasePred. Since SU is being
/// unscheduled, incrcease the succ left count of its predecessors. Remove
/// unscheduled, increase the succ left count of its predecessors. Remove
/// them from AvailableQueue if necessary.
void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {
SUnit *PredSU = PredEdge->getSUnit();
@ -934,6 +935,146 @@ static bool isOperandOf(const SUnit *SU, SDNode *N) {
return false;
}
/// TryUnfold - Attempt to unfold
SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
SDNode *N = SU->getNode();
// Use while over if to ease fall through.
SmallVector<SDNode *, 2> NewNodes;
if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes))
return nullptr;
// unfolding an x86 DEC64m operation results in store, dec, load which
// can't be handled here so quit
if (NewNodes.size() == 3)
return nullptr;
assert(NewNodes.size() == 2 && "Expected a load folding node!");
N = NewNodes[1];
SDNode *LoadNode = NewNodes[0];
unsigned NumVals = N->getNumValues();
unsigned OldNumVals = SU->getNode()->getNumValues();
// LoadNode may already exist. This can happen when there is another
// load from the same location and producing the same type of value
// but it has different alignment or volatileness.
bool isNewLoad = true;
SUnit *LoadSU;
if (LoadNode->getNodeId() != -1) {
LoadSU = &SUnits[LoadNode->getNodeId()];
// If LoadSU has already been scheduled, we should clone it but
// this would negate the benefit to unfolding so just return SU.
if (LoadSU->isScheduled)
return SU;
isNewLoad = false;
} else {
LoadSU = CreateNewSUnit(LoadNode);
LoadNode->setNodeId(LoadSU->NodeNum);
InitNumRegDefsLeft(LoadSU);
computeLatency(LoadSU);
}
DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");
// Now that we are committed to unfolding replace DAG Uses.
for (unsigned i = 0; i != NumVals; ++i)
DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1),
SDValue(LoadNode, 1));
SUnit *NewSU = CreateNewSUnit(N);
assert(N->getNodeId() == -1 && "Node already inserted!");
N->setNodeId(NewSU->NodeNum);
const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
NewSU->isTwoAddress = true;
break;
}
}
if (MCID.isCommutable())
NewSU->isCommutable = true;
InitNumRegDefsLeft(NewSU);
computeLatency(NewSU);
// Record all the edges to and from the old SU, by category.
SmallVector<SDep, 4> ChainPreds;
SmallVector<SDep, 4> ChainSuccs;
SmallVector<SDep, 4> LoadPreds;
SmallVector<SDep, 4> NodePreds;
SmallVector<SDep, 4> NodeSuccs;
for (SDep &Pred : SU->Preds) {
if (Pred.isCtrl())
ChainPreds.push_back(Pred);
else if (isOperandOf(Pred.getSUnit(), LoadNode))
LoadPreds.push_back(Pred);
else
NodePreds.push_back(Pred);
}
for (SDep &Succ : SU->Succs) {
if (Succ.isCtrl())
ChainSuccs.push_back(Succ);
else
NodeSuccs.push_back(Succ);
}
// Now assign edges to the newly-created nodes.
for (const SDep &Pred : ChainPreds) {
RemovePred(SU, Pred);
if (isNewLoad)
AddPred(LoadSU, Pred);
}
for (const SDep &Pred : LoadPreds) {
RemovePred(SU, Pred);
if (isNewLoad)
AddPred(LoadSU, Pred);
}
for (const SDep &Pred : NodePreds) {
RemovePred(SU, Pred);
AddPred(NewSU, Pred);
}
for (SDep D : NodeSuccs) {
SUnit *SuccDep = D.getSUnit();
D.setSUnit(SU);
RemovePred(SuccDep, D);
D.setSUnit(NewSU);
AddPred(SuccDep, D);
// Balance register pressure.
if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled &&
!D.isCtrl() && NewSU->NumRegDefsLeft > 0)
--NewSU->NumRegDefsLeft;
}
for (SDep D : ChainSuccs) {
SUnit *SuccDep = D.getSUnit();
D.setSUnit(SU);
RemovePred(SuccDep, D);
if (isNewLoad) {
D.setSUnit(LoadSU);
AddPred(SuccDep, D);
}
}
// Add a data dependency to reflect that NewSU reads the value defined
// by LoadSU.
SDep D(LoadSU, SDep::Data, 0);
D.setLatency(LoadSU->Latency);
AddPred(NewSU, D);
if (isNewLoad)
AvailableQueue->addNode(LoadSU);
AvailableQueue->addNode(NewSU);
++NumUnfolds;
if (NewSU->NumSuccsLeft == 0)
NewSU->isAvailable = true;
return NewSU;
}
/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled
/// successors to the newly created node.
SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
@ -959,135 +1100,16 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
return nullptr;
}
// If possible unfold instruction.
if (TryUnfold) {
SmallVector<SDNode*, 2> NewNodes;
if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes))
SUnit *UnfoldSU = TryUnfoldSU(SU);
if (!UnfoldSU)
return nullptr;
// unfolding an x86 DEC64m operation results in store, dec, load which
// can't be handled here so quit
if (NewNodes.size() == 3)
return nullptr;
DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");
assert(NewNodes.size() == 2 && "Expected a load folding node!");
N = NewNodes[1];
SDNode *LoadNode = NewNodes[0];
unsigned NumVals = N->getNumValues();
unsigned OldNumVals = SU->getNode()->getNumValues();
for (unsigned i = 0; i != NumVals; ++i)
DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1),
SDValue(LoadNode, 1));
// LoadNode may already exist. This can happen when there is another
// load from the same location and producing the same type of value
// but it has different alignment or volatileness.
bool isNewLoad = true;
SUnit *LoadSU;
if (LoadNode->getNodeId() != -1) {
LoadSU = &SUnits[LoadNode->getNodeId()];
isNewLoad = false;
} else {
LoadSU = CreateNewSUnit(LoadNode);
LoadNode->setNodeId(LoadSU->NodeNum);
InitNumRegDefsLeft(LoadSU);
computeLatency(LoadSU);
}
SUnit *NewSU = CreateNewSUnit(N);
assert(N->getNodeId() == -1 && "Node already inserted!");
N->setNodeId(NewSU->NodeNum);
const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
NewSU->isTwoAddress = true;
break;
}
}
if (MCID.isCommutable())
NewSU->isCommutable = true;
InitNumRegDefsLeft(NewSU);
computeLatency(NewSU);
// Record all the edges to and from the old SU, by category.
SmallVector<SDep, 4> ChainPreds;
SmallVector<SDep, 4> ChainSuccs;
SmallVector<SDep, 4> LoadPreds;
SmallVector<SDep, 4> NodePreds;
SmallVector<SDep, 4> NodeSuccs;
for (SDep &Pred : SU->Preds) {
if (Pred.isCtrl())
ChainPreds.push_back(Pred);
else if (isOperandOf(Pred.getSUnit(), LoadNode))
LoadPreds.push_back(Pred);
else
NodePreds.push_back(Pred);
}
for (SDep &Succ : SU->Succs) {
if (Succ.isCtrl())
ChainSuccs.push_back(Succ);
else
NodeSuccs.push_back(Succ);
}
// Now assign edges to the newly-created nodes.
for (const SDep &Pred : ChainPreds) {
RemovePred(SU, Pred);
if (isNewLoad)
AddPred(LoadSU, Pred);
}
for (const SDep &Pred : LoadPreds) {
RemovePred(SU, Pred);
if (isNewLoad)
AddPred(LoadSU, Pred);
}
for (const SDep &Pred : NodePreds) {
RemovePred(SU, Pred);
AddPred(NewSU, Pred);
}
for (SDep D : NodeSuccs) {
SUnit *SuccDep = D.getSUnit();
D.setSUnit(SU);
RemovePred(SuccDep, D);
D.setSUnit(NewSU);
AddPred(SuccDep, D);
// Balance register pressure.
if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled
&& !D.isCtrl() && NewSU->NumRegDefsLeft > 0)
--NewSU->NumRegDefsLeft;
}
for (SDep D : ChainSuccs) {
SUnit *SuccDep = D.getSUnit();
D.setSUnit(SU);
RemovePred(SuccDep, D);
if (isNewLoad) {
D.setSUnit(LoadSU);
AddPred(SuccDep, D);
}
}
// Add a data dependency to reflect that NewSU reads the value defined
// by LoadSU.
SDep D(LoadSU, SDep::Data, 0);
D.setLatency(LoadSU->Latency);
AddPred(NewSU, D);
if (isNewLoad)
AvailableQueue->addNode(LoadSU);
AvailableQueue->addNode(NewSU);
++NumUnfolds;
if (NewSU->NumSuccsLeft == 0) {
NewSU->isAvailable = true;
return NewSU;
}
SU = NewSU;
SU = UnfoldSU;
N = SU->getNode();
// If this can be scheduled don't bother duplicating and just return
if (SU->NumSuccsLeft == 0)
return SU;
}
DEBUG(dbgs() << " Duplicating SU #" << SU->NodeNum << "\n");

View File

@ -214,6 +214,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FPOWI: return "fpowi";
case ISD::SETCC: return "setcc";
case ISD::SETCCE: return "setcce";
case ISD::SETCCCARRY: return "setcccarry";
case ISD::SELECT: return "select";
case ISD::VSELECT: return "vselect";
case ISD::SELECT_CC: return "select_cc";

View File

@ -842,9 +842,10 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) {
initActions();
// Perform these initializations only once.
MaxStoresPerMemset = MaxStoresPerMemcpy = MaxStoresPerMemmove = 8;
MaxStoresPerMemsetOptSize = MaxStoresPerMemcpyOptSize
= MaxStoresPerMemmoveOptSize = 4;
MaxStoresPerMemset = MaxStoresPerMemcpy = MaxStoresPerMemmove =
MaxLoadsPerMemcmp = 8;
MaxStoresPerMemsetOptSize = MaxStoresPerMemcpyOptSize =
MaxStoresPerMemmoveOptSize = MaxLoadsPerMemcmpOptSize = 4;
UseUnderscoreSetJmp = false;
UseUnderscoreLongJmp = false;
HasMultipleConditionRegisters = false;
@ -926,6 +927,7 @@ void TargetLoweringBase::initActions() {
// ADDCARRY operations default to expand
setOperationAction(ISD::ADDCARRY, VT, Expand);
setOperationAction(ISD::SUBCARRY, VT, Expand);
setOperationAction(ISD::SETCCCARRY, VT, Expand);
// These default to Expand so they will be expanded to CTLZ/CTTZ by default.
setOperationAction(ISD::CTLZ_ZERO_UNDEF, VT, Expand);

View File

@ -261,9 +261,9 @@ TargetPassConfig::~TargetPassConfig() {
// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
: ImmutablePass(ID), PM(&pm), Started(true), Stopped(false),
AddingMachinePasses(false), TM(tm), Impl(nullptr), Initialized(false),
AddingMachinePasses(false), TM(&TM), Impl(nullptr), Initialized(false),
DisableVerify(false), EnableTailMerge(true),
RequireCodeGenSCCOrder(false) {
@ -282,9 +282,9 @@ TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
substitutePass(&PostRAMachineLICMID, &MachineLICMID);
if (StringRef(PrintMachineInstrs.getValue()).equals(""))
TM->Options.PrintMachineCode = true;
TM.Options.PrintMachineCode = true;
if (TM->Options.EnableIPRA)
if (TM.Options.EnableIPRA)
setRequiresCodeGenSCCOrder();
}
@ -310,7 +310,7 @@ void TargetPassConfig::insertPass(AnalysisID TargetPassID,
///
/// Targets may override this to extend TargetPassConfig.
TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {
return new TargetPassConfig(this, PM);
return new TargetPassConfig(*this, PM);
}
TargetPassConfig::TargetPassConfig()
@ -430,7 +430,12 @@ void TargetPassConfig::addPrintPass(const std::string &Banner) {
}
void TargetPassConfig::addVerifyPass(const std::string &Banner) {
if (VerifyMachineCode)
bool Verify = VerifyMachineCode;
#ifdef EXPENSIVE_CHECKS
if (VerifyMachineCode == cl::BOU_UNSET)
Verify = TM->isMachineVerifierClean();
#endif
if (Verify)
PM->add(createMachineVerifierPass(Banner));
}

View File

@ -46,7 +46,7 @@ Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
}
if (auto EC = Callbacks.visitSymbolEnd(Record))

View File

@ -71,7 +71,7 @@ static Error visitMemberRecord(CVMemberRecord &Record,
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
}
if (auto EC = Callbacks.visitMemberEnd(Record))
@ -155,7 +155,7 @@ Error CVTypeVisitor::finishVisitation(CVType &Record) {
TYPE_RECORD(EnumVal, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
}
if (auto EC = Callbacks.visitTypeEnd(Record))

View File

@ -20,13 +20,13 @@ using namespace codeview;
static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
#define CV_SYMBOL(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
#undef CV_SYMBOL
};
static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
#define CV_TYPE(name, val) {#name, name},
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
#undef CV_TYPE
};

View File

@ -41,7 +41,7 @@ class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
Error visitSymbolBegin(CVSymbol &Record) override;
Error visitSymbolEnd(CVSymbol &Record) override;

View File

@ -26,7 +26,7 @@ using namespace llvm::codeview;
static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
};
#define ENUM_ENTRY(enum_class, enum) \
@ -155,7 +155,7 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
#define TYPE_RECORD(ename, value, name) \
case ename: \
return #name;
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
default:
break;
}

View File

@ -84,8 +84,12 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
Accel.dump(OS);
}
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
bool SummarizeTypes) {
void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){
DIDumpType DumpType = DumpOpts.DumpType;
bool DumpEH = DumpOpts.DumpEH;
bool SummarizeTypes = DumpOpts.SummarizeTypes;
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);

View File

@ -79,6 +79,7 @@ Error InfoStream::reload() {
break;
case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
Features |= PdbFeatureMinimalDebugInfo;
break;
default:
continue;
}

View File

@ -29,8 +29,7 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
Session->setLoadAddress(ImageBase.get());
}
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
bool SummarizeTypes) {}
void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {

View File

@ -4,11 +4,11 @@ RUN: sancov -covered-functions LLVMFuzzer-NullDerefTest* %t_workdir/*.sancov | F
RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' LLVMFuzzer-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not LLVMFuzzer-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV
CHECK: SanitizerCoverage: {{.*}}LLVMFuzzer-NullDerefTest.{{.*}}.sancov {{.*}} PCs written
CHECK: SanitizerCoverage: {{.*}}LLVMFuzzer-NullDerefTest.{{.*}}.sancov: {{.*}} PCs written
SANCOV: LLVMFuzzerTestOneInput
DSO: SanitizerCoverage: {{.*}}LLVMFuzzer-DSOTest.{{.*}}.sancov {{.*}} PCs written
DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO1.{{.*}}.sancov {{.*}} PCs written
DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO2.{{.*}}.sancov {{.*}} PCs written
DSO: SanitizerCoverage: {{.*}}LLVMFuzzer-DSOTest.{{.*}}.sancov: {{.*}} PCs written
DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO1.{{.*}}.sancov: {{.*}} PCs written
DSO-DAG: SanitizerCoverage: {{.*}}LLVMFuzzer-DSO2.{{.*}}.sancov: {{.*}} PCs written
NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written

View File

@ -1006,6 +1006,10 @@ AttributeList AttributeList::get(LLVMContext &C,
for (AttributeList List : Attrs)
MaxSize = std::max(MaxSize, List.getNumAttrSets());
// If every list was empty, there is no point in merging the lists.
if (MaxSize == 0)
return AttributeList();
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
for (unsigned I = 0; I < MaxSize; ++I) {
AttrBuilder CurBuilder;
@ -1033,24 +1037,11 @@ AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
return addAttributes(C, Index, B);
}
AttributeList AttributeList::addAttribute(LLVMContext &C,
ArrayRef<unsigned> Indices,
AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
Attribute A) const {
assert(std::is_sorted(Indices.begin(), Indices.end()));
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
unsigned MaxIndex = attrIdxToArrayIdx(Indices.back());
if (MaxIndex >= AttrSets.size())
AttrSets.resize(MaxIndex + 1);
for (unsigned Index : Indices) {
Index = attrIdxToArrayIdx(Index);
AttrBuilder B(AttrSets[Index]);
B.addAttribute(A);
AttrSets[Index] = AttributeSet::get(C, B);
}
return getImpl(C, AttrSets);
AttrBuilder B;
B.addAttribute(A);
return addAttributes(C, Index, B);
}
AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
@ -1082,6 +1073,26 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
return getImpl(C, AttrSets);
}
AttributeList AttributeList::addParamAttribute(LLVMContext &C,
ArrayRef<unsigned> ArgNos,
Attribute A) const {
assert(std::is_sorted(ArgNos.begin(), ArgNos.end()));
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
if (MaxIndex >= AttrSets.size())
AttrSets.resize(MaxIndex + 1);
for (unsigned ArgNo : ArgNos) {
unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
AttrBuilder B(AttrSets[Index]);
B.addAttribute(A);
AttrSets[Index] = AttributeSet::get(C, B);
}
return getImpl(C, AttrSets);
}
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Index, Kind)) return *this;

Some files were not shown because too many files have changed in this diff Show More