1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-18 02:19:39 +00:00

Merge llvm, clang, lld and lldb trunk r300890, and update build glue.

This commit is contained in:
Dimitry Andric 2017-04-20 21:48:54 +00:00
commit 6bc11b1414
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang500-import/; revision=317230
372 changed files with 9125 additions and 4740 deletions

View File

@ -2130,6 +2130,16 @@ LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
*/
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
/**
* Obtain a Metadata as a Value.
*/
LLVMValueRef LLVMMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD);
/**
* Obtain a Value as a Metadata.
*/
LLVMMetadataRef LLVMValueAsMetadata(LLVMValueRef Val);
/**
* Obtain the underlying string from a MDString value.
*

View File

@ -82,6 +82,13 @@ typedef struct LLVMOpaqueValue *LLVMValueRef;
*/
typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
/**
* Represents an LLVM Metadata.
*
* This models llvm::Metadata.
*/
typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
/**
* Represents an LLVM basic block builder.
*
@ -89,6 +96,13 @@ typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
*/
typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
/**
* Represents an LLVM debug info builder.
*
* This models llvm::DIBuilder.
*/
typedef struct LLVMOpaqueDIBuilder *LLVMDIBuilderRef;
/**
* Interface used to provide a module to JIT or interpreter.
* This is now just a synonym for llvm::Module, but we have to keep using the

View File

@ -189,17 +189,17 @@ class LLVM_NODISCARD APInt {
void initSlowCase(const APInt &that);
/// out-of-line slow case for shl
APInt shlSlowCase(unsigned shiftAmt) const;
void shlSlowCase(unsigned ShiftAmt);
/// out-of-line slow case for lshr.
void lshrSlowCase(unsigned ShiftAmt);
/// out-of-line slow case for operator=
APInt &AssignSlowCase(const APInt &RHS);
void AssignSlowCase(const APInt &RHS);
/// out-of-line slow case for operator==
bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
/// out-of-line slow case for operator==
bool EqualSlowCase(uint64_t Val) const LLVM_READONLY;
/// out-of-line slow case for countLeadingZeros
unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
@ -209,6 +209,12 @@ class LLVM_NODISCARD APInt {
/// out-of-line slow case for countPopulation
unsigned countPopulationSlowCase() const LLVM_READONLY;
/// out-of-line slow case for intersects.
bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY;
/// out-of-line slow case for isSubsetOf.
bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY;
/// out-of-line slow case for setBits.
void setBitsSlowCase(unsigned loBit, unsigned hiBit);
@ -216,13 +222,13 @@ class LLVM_NODISCARD APInt {
void flipAllBitsSlowCase();
/// out-of-line slow case for operator&=.
APInt& AndAssignSlowCase(const APInt& RHS);
void AndAssignSlowCase(const APInt& RHS);
/// out-of-line slow case for operator|=.
APInt& OrAssignSlowCase(const APInt& RHS);
void OrAssignSlowCase(const APInt& RHS);
/// out-of-line slow case for operator^=.
APInt& XorAssignSlowCase(const APInt& RHS);
void XorAssignSlowCase(const APInt& RHS);
public:
/// \name Constructors
@ -330,6 +336,20 @@ class LLVM_NODISCARD APInt {
/// This tests the high bit of the APInt to determine if it is unset.
bool isNonNegative() const { return !isNegative(); }
/// \brief Determine if sign bit of this APInt is set.
///
/// This tests the high bit of this APInt to determine if it is set.
///
/// \returns true if this APInt has its sign bit set, false otherwise.
bool isSignBitSet() const { return (*this)[BitWidth-1]; }
/// \brief Determine if sign bit of this APInt is clear.
///
/// This tests the high bit of this APInt to determine if it is clear.
///
/// \returns true if this APInt has its sign bit clear, false otherwise.
bool isSignBitClear() const { return !isSignBitSet(); }
/// \brief Determine if this APInt Value is positive.
///
/// This tests if the value of this APInt is positive (> 0). Note
@ -396,10 +416,10 @@ class LLVM_NODISCARD APInt {
return countPopulationSlowCase() == 1;
}
/// \brief Check if the APInt's value is returned by getSignBit.
/// \brief Check if the APInt's value is returned by getSignMask.
///
/// \returns true if this is the value returned by getSignBit.
bool isSignBit() const { return isMinSignedValue(); }
/// \returns true if this is the value returned by getSignMask.
bool isSignMask() const { return isMinSignedValue(); }
/// \brief Convert APInt to a boolean value.
///
@ -409,8 +429,7 @@ class LLVM_NODISCARD APInt {
/// If this value is smaller than the specified limit, return it, otherwise
/// return the limit value. This causes the value to saturate to the limit.
uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) const {
return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit
: getZExtValue();
return ugt(Limit) ? Limit : getZExtValue();
}
/// \brief Check if the APInt consists of a repeated bit pattern.
@ -427,8 +446,9 @@ class LLVM_NODISCARD APInt {
assert(numBits <= BitWidth && "numBits out of range");
if (isSingleWord())
return VAL == (UINT64_MAX >> (APINT_BITS_PER_WORD - numBits));
unsigned Ones = countTrailingOnes();
return (numBits == Ones) && ((Ones + countLeadingZeros()) == BitWidth);
unsigned Ones = countTrailingOnesSlowCase();
return (numBits == Ones) &&
((Ones + countLeadingZerosSlowCase()) == BitWidth);
}
/// \returns true if this APInt is a non-empty sequence of ones starting at
@ -437,8 +457,8 @@ class LLVM_NODISCARD APInt {
bool isMask() const {
if (isSingleWord())
return isMask_64(VAL);
unsigned Ones = countTrailingOnes();
return (Ones > 0) && ((Ones + countLeadingZeros()) == BitWidth);
unsigned Ones = countTrailingOnesSlowCase();
return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth);
}
/// \brief Return true if this APInt value contains a sequence of ones with
@ -446,8 +466,9 @@ class LLVM_NODISCARD APInt {
bool isShiftedMask() const {
if (isSingleWord())
return isShiftedMask_64(VAL);
unsigned Ones = countPopulation();
return (Ones + countTrailingZeros() + countLeadingZeros()) == BitWidth;
unsigned Ones = countPopulationSlowCase();
unsigned LeadZ = countLeadingZerosSlowCase();
return (Ones + LeadZ + countTrailingZeros()) == BitWidth;
}
/// @}
@ -476,11 +497,11 @@ class LLVM_NODISCARD APInt {
return API;
}
/// \brief Get the SignBit for a specific bit width.
/// \brief Get the SignMask for a specific bit width.
///
/// This is just a wrapper function of getSignedMinValue(), and it helps code
/// readability when we want to get a SignBit.
static APInt getSignBit(unsigned BitWidth) {
/// readability when we want to get a SignMask.
static APInt getSignMask(unsigned BitWidth) {
return getSignedMinValue(BitWidth);
}
@ -674,29 +695,22 @@ class LLVM_NODISCARD APInt {
return clearUnusedBits();
}
return AssignSlowCase(RHS);
AssignSlowCase(RHS);
return *this;
}
/// @brief Move assignment operator.
APInt &operator=(APInt &&that) {
if (!isSingleWord()) {
// The MSVC STL shipped in 2013 requires that self move assignment be a
// no-op. Otherwise algorithms like stable_sort will produce answers
// where half of the output is left in a moved-from state.
if (this == &that)
return *this;
assert(this != &that && "Self-move not supported");
if (!isSingleWord())
delete[] pVal;
}
// Use memcpy so that type based alias analysis sees both VAL and pVal
// as modified.
memcpy(&VAL, &that.VAL, sizeof(uint64_t));
// If 'this == &that', avoid zeroing our own bitwidth by storing to 'that'
// first.
unsigned ThatBitWidth = that.BitWidth;
BitWidth = that.BitWidth;
that.BitWidth = 0;
BitWidth = ThatBitWidth;
return *this;
}
@ -727,11 +741,11 @@ class LLVM_NODISCARD APInt {
/// \returns *this after ANDing with RHS.
APInt &operator&=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
if (isSingleWord())
VAL &= RHS.VAL;
return *this;
}
return AndAssignSlowCase(RHS);
else
AndAssignSlowCase(RHS);
return *this;
}
/// \brief Bitwise AND assignment operator.
@ -757,11 +771,11 @@ class LLVM_NODISCARD APInt {
/// \returns *this after ORing with RHS.
APInt &operator|=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
if (isSingleWord())
VAL |= RHS.VAL;
return *this;
}
return OrAssignSlowCase(RHS);
else
OrAssignSlowCase(RHS);
return *this;
}
/// \brief Bitwise OR assignment operator.
@ -787,11 +801,11 @@ class LLVM_NODISCARD APInt {
/// \returns *this after XORing with RHS.
APInt &operator^=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
if (isSingleWord())
VAL ^= RHS.VAL;
return *this;
}
return XorAssignSlowCase(RHS);
else
XorAssignSlowCase(RHS);
return *this;
}
/// \brief Bitwise XOR assignment operator.
@ -836,9 +850,17 @@ class LLVM_NODISCARD APInt {
///
/// Shifts *this left by shiftAmt and assigns the result to *this.
///
/// \returns *this after shifting left by shiftAmt
APInt &operator<<=(unsigned shiftAmt) {
*this = shl(shiftAmt);
/// \returns *this after shifting left by ShiftAmt
APInt &operator<<=(unsigned ShiftAmt) {
assert(ShiftAmt <= BitWidth && "Invalid shift amount");
if (isSingleWord()) {
if (ShiftAmt == BitWidth)
VAL = 0;
else
VAL <<= ShiftAmt;
return clearUnusedBits();
}
shlSlowCase(ShiftAmt);
return *this;
}
@ -875,20 +897,26 @@ class LLVM_NODISCARD APInt {
return R;
}
/// Logical right-shift this APInt by shiftAmt in place.
void lshrInPlace(unsigned shiftAmt);
/// Logical right-shift this APInt by ShiftAmt in place.
void lshrInPlace(unsigned ShiftAmt) {
assert(ShiftAmt <= BitWidth && "Invalid shift amount");
if (isSingleWord()) {
if (ShiftAmt == BitWidth)
VAL = 0;
else
VAL >>= ShiftAmt;
return;
}
lshrSlowCase(ShiftAmt);
}
/// \brief Left-shift function.
///
/// Left-shift this APInt by shiftAmt.
APInt shl(unsigned shiftAmt) const {
assert(shiftAmt <= BitWidth && "Invalid shift amount");
if (isSingleWord()) {
if (shiftAmt >= BitWidth)
return APInt(BitWidth, 0); // avoid undefined shift results
return APInt(BitWidth, VAL << shiftAmt);
}
return shlSlowCase(shiftAmt);
APInt R(*this);
R <<= shiftAmt;
return R;
}
/// \brief Rotate left by rotateAmt.
@ -905,7 +933,14 @@ class LLVM_NODISCARD APInt {
/// \brief Logical right-shift function.
///
/// Logical right-shift this APInt by shiftAmt.
APInt lshr(const APInt &shiftAmt) const;
APInt lshr(const APInt &ShiftAmt) const {
APInt R(*this);
R.lshrInPlace(ShiftAmt);
return R;
}
/// Logical right-shift this APInt by ShiftAmt in place.
void lshrInPlace(const APInt &ShiftAmt);
/// \brief Left-shift function.
///
@ -1003,9 +1038,7 @@ class LLVM_NODISCARD APInt {
///
/// \returns true if *this == Val
bool operator==(uint64_t Val) const {
if (isSingleWord())
return VAL == Val;
return EqualSlowCase(Val);
return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() == Val;
}
/// \brief Equality comparison.
@ -1055,7 +1088,8 @@ class LLVM_NODISCARD APInt {
///
/// \returns true if *this < RHS when considered unsigned.
bool ult(uint64_t RHS) const {
return getActiveBits() > 64 ? false : getZExtValue() < RHS;
// Only need to check active bits if not a single word.
return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() < RHS;
}
/// \brief Signed less than comparison
@ -1073,7 +1107,8 @@ class LLVM_NODISCARD APInt {
///
/// \returns true if *this < RHS when considered signed.
bool slt(int64_t RHS) const {
return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS;
return (!isSingleWord() && getMinSignedBits() > 64) ? isNegative()
: getSExtValue() < RHS;
}
/// \brief Unsigned less or equal comparison
@ -1123,7 +1158,8 @@ class LLVM_NODISCARD APInt {
///
/// \returns true if *this > RHS when considered unsigned.
bool ugt(uint64_t RHS) const {
return getActiveBits() > 64 ? true : getZExtValue() > RHS;
// Only need to check active bits if not a single word.
return (!isSingleWord() && getActiveBits() > 64) || getZExtValue() > RHS;
}
/// \brief Signed greather than comparison
@ -1141,7 +1177,8 @@ class LLVM_NODISCARD APInt {
///
/// \returns true if *this > RHS when considered signed.
bool sgt(int64_t RHS) const {
return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS;
return (!isSingleWord() && getMinSignedBits() > 64) ? !isNegative()
: getSExtValue() > RHS;
}
/// \brief Unsigned greater or equal comparison
@ -1179,9 +1216,18 @@ class LLVM_NODISCARD APInt {
/// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set.
bool intersects(const APInt &RHS) const {
APInt temp(*this);
temp &= RHS;
return temp != 0;
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return (VAL & RHS.VAL) != 0;
return intersectsSlowCase(RHS);
}
/// This operation checks that all bits set in this APInt are also set in RHS.
bool isSubsetOf(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return (VAL & ~RHS.VAL) == 0;
return isSubsetOfSlowCase(RHS);
}
/// @}
@ -1404,8 +1450,7 @@ class LLVM_NODISCARD APInt {
/// int64_t. Otherwise an assertion will result.
int64_t getSExtValue() const {
if (isSingleWord())
return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >>
(APINT_BITS_PER_WORD - BitWidth);
return SignExtend64(VAL, BitWidth);
assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
return int64_t(pVal[0]);
}
@ -1759,13 +1804,13 @@ class LLVM_NODISCARD APInt {
WordType *remainder, WordType *scratch,
unsigned parts);
/// Shift a bignum left COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
static void tcShiftLeft(WordType *, unsigned parts, unsigned count);
/// Shift a bignum left Count bits. Shifted in bits are zero. There are no
/// restrictions on Count.
static void tcShiftLeft(WordType *, unsigned Words, unsigned Count);
/// Shift a bignum right COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
static void tcShiftRight(WordType *, unsigned parts, unsigned count);
/// Shift a bignum right Count bits. Shifted in bits are zero. There are no
/// restrictions on Count.
static void tcShiftRight(WordType *, unsigned Words, unsigned Count);
/// The obvious AND, OR and XOR and complement operations.
static void tcAnd(WordType *, const WordType *, unsigned);
@ -1959,7 +2004,7 @@ inline const APInt &umax(const APInt &A, const APInt &B) {
/// \brief Compute GCD of two unsigned APInt values.
///
/// This function returns the greatest common divisor of the two APInt values
/// using Euclid's algorithm.
/// using Stein's algorithm.
///
/// \returns the greatest common divisor of A and B.
APInt GreatestCommonDivisor(APInt A, APInt B);

View File

@ -14,6 +14,8 @@
#ifndef LLVM_ADT_BITVECTOR_H
#define LLVM_ADT_BITVECTOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
@ -455,6 +457,105 @@ class BitVector {
return *this;
}
BitVector &operator>>=(unsigned N) {
assert(N <= Size);
if (LLVM_UNLIKELY(empty() || N == 0))
return *this;
unsigned NumWords = NumBitWords(Size);
assert(NumWords >= 1);
wordShr(N / BITWORD_SIZE);
unsigned BitDistance = N % BITWORD_SIZE;
if (BitDistance == 0)
return *this;
// When the shift size is not a multiple of the word size, then we have
// a tricky situation where each word in succession needs to extract some
// of the bits from the next word and or them into this word while
// shifting this word to make room for the new bits. This has to be done
// for every word in the array.
// Since we're shifting each word right, some bits will fall off the end
// of each word to the right, and empty space will be created on the left.
// The final word in the array will lose bits permanently, so starting at
// the beginning, work forwards shifting each word to the right, and
// OR'ing in the bits from the end of the next word to the beginning of
// the current word.
// Example:
// Starting with {0xAABBCCDD, 0xEEFF0011, 0x22334455} and shifting right
// by 4 bits.
// Step 1: Word[0] >>= 4 ; 0x0ABBCCDD
// Step 2: Word[0] |= 0x10000000 ; 0x1ABBCCDD
// Step 3: Word[1] >>= 4 ; 0x0EEFF001
// Step 4: Word[1] |= 0x50000000 ; 0x5EEFF001
// Step 5: Word[2] >>= 4 ; 0x02334455
// Result: { 0x1ABBCCDD, 0x5EEFF001, 0x02334455 }
const BitWord Mask = maskTrailingOnes<BitWord>(BitDistance);
const unsigned LSH = BITWORD_SIZE - BitDistance;
for (unsigned I = 0; I < NumWords - 1; ++I) {
Bits[I] >>= BitDistance;
Bits[I] |= (Bits[I + 1] & Mask) << LSH;
}
Bits[NumWords - 1] >>= BitDistance;
return *this;
}
BitVector &operator<<=(unsigned N) {
assert(N <= Size);
if (LLVM_UNLIKELY(empty() || N == 0))
return *this;
unsigned NumWords = NumBitWords(Size);
assert(NumWords >= 1);
wordShl(N / BITWORD_SIZE);
unsigned BitDistance = N % BITWORD_SIZE;
if (BitDistance == 0)
return *this;
// When the shift size is not a multiple of the word size, then we have
// a tricky situation where each word in succession needs to extract some
// of the bits from the previous word and or them into this word while
// shifting this word to make room for the new bits. This has to be done
// for every word in the array. This is similar to the algorithm outlined
// in operator>>=, but backwards.
// Since we're shifting each word left, some bits will fall off the end
// of each word to the left, and empty space will be created on the right.
// The first word in the array will lose bits permanently, so starting at
// the end, work backwards shifting each word to the left, and OR'ing
// in the bits from the end of the next word to the beginning of the
// current word.
// Example:
// Starting with {0xAABBCCDD, 0xEEFF0011, 0x22334455} and shifting left
// by 4 bits.
// Step 1: Word[2] <<= 4 ; 0x23344550
// Step 2: Word[2] |= 0x0000000E ; 0x2334455E
// Step 3: Word[1] <<= 4 ; 0xEFF00110
// Step 4: Word[1] |= 0x0000000A ; 0xEFF0011A
// Step 5: Word[0] <<= 4 ; 0xABBCCDD0
// Result: { 0xABBCCDD0, 0xEFF0011A, 0x2334455E }
const BitWord Mask = maskLeadingOnes<BitWord>(BitDistance);
const unsigned RSH = BITWORD_SIZE - BitDistance;
for (int I = NumWords - 1; I > 0; --I) {
Bits[I] <<= BitDistance;
Bits[I] |= (Bits[I - 1] & Mask) >> RSH;
}
Bits[0] <<= BitDistance;
clear_unused_bits();
return *this;
}
// Assignment operator.
const BitVector &operator=(const BitVector &RHS) {
if (this == &RHS) return *this;
@ -538,6 +639,54 @@ class BitVector {
}
private:
/// \brief Perform a logical left shift of \p Count words by moving everything
/// \p Count words to the right in memory.
///
/// While confusing, words are stored from least significant at Bits[0] to
/// most significant at Bits[NumWords-1]. A logical shift left, however,
/// moves the current least significant bit to a higher logical index, and
/// fills the previous least significant bits with 0. Thus, we actually
/// need to move the bytes of the memory to the right, not to the left.
/// Example:
/// Words = [0xBBBBAAAA, 0xDDDDFFFF, 0x00000000, 0xDDDD0000]
/// represents a BitVector where 0xBBBBAAAA contain the least significant
/// bits. So if we want to shift the BitVector left by 2 words, we need to
/// turn this into 0x00000000 0x00000000 0xBBBBAAAA 0xDDDDFFFF by using a
/// memmove which moves right, not left.
void wordShl(uint32_t Count) {
if (Count == 0)
return;
uint32_t NumWords = NumBitWords(Size);
auto Src = ArrayRef<BitWord>(Bits, NumWords).drop_back(Count);
auto Dest = MutableArrayRef<BitWord>(Bits, NumWords).drop_front(Count);
// Since we always move Word-sized chunks of data with src and dest both
// aligned to a word-boundary, we don't need to worry about endianness
// here.
std::memmove(Dest.begin(), Src.begin(), Dest.size() * sizeof(BitWord));
std::memset(Bits, 0, Count * sizeof(BitWord));
clear_unused_bits();
}
/// \brief Perform a logical right shift of \p Count words by moving those
/// words to the left in memory. See wordShl for more information.
///
void wordShr(uint32_t Count) {
if (Count == 0)
return;
uint32_t NumWords = NumBitWords(Size);
auto Src = ArrayRef<BitWord>(Bits, NumWords).drop_front(Count);
auto Dest = MutableArrayRef<BitWord>(Bits, NumWords).drop_back(Count);
assert(Dest.size() == Src.size());
std::memmove(Dest.begin(), Src.begin(), Dest.size() * sizeof(BitWord));
std::memset(Dest.end(), 0, Count * sizeof(BitWord));
}
int next_unset_in_word(int WordIndex, BitWord Word) const {
unsigned Result = WordIndex * BITWORD_SIZE + countTrailingOnes(Word);
return Result < size() ? Result : -1;

View File

@ -508,6 +508,22 @@ class SmallBitVector {
return *this;
}
SmallBitVector &operator<<=(unsigned N) {
if (isSmall())
setSmallBits(getSmallBits() << N);
else
getPointer()->operator<<=(N);
return *this;
}
SmallBitVector &operator>>=(unsigned N) {
if (isSmall())
setSmallBits(getSmallBits() >> N);
else
getPointer()->operator>>=(N);
return *this;
}
// Assignment operator.
const SmallBitVector &operator=(const SmallBitVector &RHS) {
if (isSmall()) {

View File

@ -1164,9 +1164,8 @@ template <class BT> struct BlockEdgesAdder {
void operator()(IrreducibleGraph &G, IrreducibleGraph::IrrNode &Irr,
const LoopData *OuterLoop) {
const BlockT *BB = BFI.RPOT[Irr.Node.Index];
for (auto I = Successor::child_begin(BB), E = Successor::child_end(BB);
I != E; ++I)
G.addEdge(Irr, BFI.getNode(*I), OuterLoop);
for (const auto Succ : children<const BlockT *>(BB))
G.addEdge(Irr, BFI.getNode(Succ), OuterLoop);
}
};
}
@ -1210,10 +1209,9 @@ BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop,
return false;
} else {
const BlockT *BB = getBlock(Node);
for (auto SI = Successor::child_begin(BB), SE = Successor::child_end(BB);
SI != SE; ++SI)
if (!addToDist(Dist, OuterLoop, Node, getNode(*SI),
getWeightFromBranchProb(BPI->getEdgeProbability(BB, SI))))
for (const auto Succ : children<const BlockT *>(BB))
if (!addToDist(Dist, OuterLoop, Node, getNode(Succ),
getWeightFromBranchProb(BPI->getEdgeProbability(BB, Succ))))
// Irreducible backedge.
return false;
}

View File

@ -174,12 +174,10 @@ ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT,
// Visit each block only once.
if (visited.insert(currentBB).second) {
// Loop over CFG successors to calculate DFlocal[currentNode]
for (auto SI = BlockTraits::child_begin(currentBB),
SE = BlockTraits::child_end(currentBB);
SI != SE; ++SI) {
for (const auto Succ : children<BlockT *>(currentBB)) {
// Does Node immediately dominate this successor?
if (DT[*SI]->getIDom() != currentNode)
S.insert(*SI);
if (DT[Succ]->getIDom() != currentNode)
S.insert(Succ);
}
}

View File

@ -158,11 +158,8 @@ class LoopBase {
/// True if terminator in the block can branch to another block that is
/// outside of the current loop.
bool isLoopExiting(const BlockT *BB) const {
typedef GraphTraits<const BlockT*> BlockTraits;
for (typename BlockTraits::ChildIteratorType SI =
BlockTraits::child_begin(BB),
SE = BlockTraits::child_end(BB); SI != SE; ++SI) {
if (!contains(*SI))
for (const auto Succ : children<const BlockT*>(BB)) {
if (!contains(Succ))
return true;
}
return false;
@ -186,11 +183,8 @@ class LoopBase {
unsigned NumBackEdges = 0;
BlockT *H = getHeader();
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
for (typename InvBlockTraits::ChildIteratorType I =
InvBlockTraits::child_begin(H),
E = InvBlockTraits::child_end(H); I != E; ++I)
if (contains(*I))
for (const auto Pred : children<Inverse<BlockT*> >(H))
if (contains(Pred))
++NumBackEdges;
return NumBackEdges;
@ -249,12 +243,9 @@ class LoopBase {
/// contains a branch back to the header.
void getLoopLatches(SmallVectorImpl<BlockT *> &LoopLatches) const {
BlockT *H = getHeader();
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
for (typename InvBlockTraits::ChildIteratorType I =
InvBlockTraits::child_begin(H),
E = InvBlockTraits::child_end(H); I != E; ++I)
if (contains(*I))
LoopLatches.push_back(*I);
for (const auto Pred : children<Inverse<BlockT*>>(H))
if (contains(Pred))
LoopLatches.push_back(Pred);
}
//===--------------------------------------------------------------------===//

View File

@ -34,14 +34,11 @@ namespace llvm {
template<class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::
getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const {
typedef GraphTraits<BlockT*> BlockTraits;
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
for (typename BlockTraits::ChildIteratorType I =
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
I != E; ++I)
if (!contains(*I)) {
for (const auto BB : blocks())
for (const auto Succ : children<BlockT*>(BB))
if (!contains(Succ)) {
// Not in current loop? It must be an exit block.
ExitingBlocks.push_back(*BI);
ExitingBlocks.push_back(BB);
break;
}
}
@ -63,14 +60,11 @@ BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
template<class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::
getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const {
typedef GraphTraits<BlockT*> BlockTraits;
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
for (typename BlockTraits::ChildIteratorType I =
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
I != E; ++I)
if (!contains(*I))
for (const auto BB : blocks())
for (const auto Succ : children<BlockT*>(BB))
if (!contains(Succ))
// Not in current loop? It must be an exit block.
ExitBlocks.push_back(*I);
ExitBlocks.push_back(Succ);
}
/// getExitBlock - If getExitBlocks would return exactly one block,
@ -88,14 +82,11 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
template<class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::
getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
typedef GraphTraits<BlockT*> BlockTraits;
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
for (typename BlockTraits::ChildIteratorType I =
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
I != E; ++I)
if (!contains(*I))
for (const auto BB : blocks())
for (const auto Succ : children<BlockT*>(BB))
if (!contains(Succ))
// Not in current loop? It must be an exit block.
ExitEdges.push_back(Edge(*BI, *I));
ExitEdges.emplace_back(BB, Succ);
}
/// getLoopPreheader - If there is a preheader for this loop, return it. A
@ -134,15 +125,11 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
// Loop over the predecessors of the header node...
BlockT *Header = getHeader();
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
for (typename InvBlockTraits::ChildIteratorType PI =
InvBlockTraits::child_begin(Header),
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
typename InvBlockTraits::NodeRef N = *PI;
if (!contains(N)) { // If the block is not in the loop...
if (Out && Out != N)
for (const auto Pred : children<Inverse<BlockT*>>(Header)) {
if (!contains(Pred)) { // If the block is not in the loop...
if (Out && Out != Pred)
return nullptr; // Multiple predecessors outside the loop
Out = N;
Out = Pred;
}
}
@ -156,17 +143,11 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
template<class BlockT, class LoopT>
BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
BlockT *Header = getHeader();
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
typename InvBlockTraits::ChildIteratorType PI =
InvBlockTraits::child_begin(Header);
typename InvBlockTraits::ChildIteratorType PE =
InvBlockTraits::child_end(Header);
BlockT *Latch = nullptr;
for (; PI != PE; ++PI) {
typename InvBlockTraits::NodeRef N = *PI;
if (contains(N)) {
for (const auto Pred : children<Inverse<BlockT*>>(Header)) {
if (contains(Pred)) {
if (Latch) return nullptr;
Latch = N;
Latch = Pred;
}
}
@ -394,11 +375,9 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
// within this subloop tree itself. Note that a predecessor may directly
// reach another subloop that is not yet discovered to be a subloop of
// this loop, which we must traverse.
for (typename InvBlockTraits::ChildIteratorType PI =
InvBlockTraits::child_begin(PredBB),
PE = InvBlockTraits::child_end(PredBB); PI != PE; ++PI) {
if (LI->getLoopFor(*PI) != Subloop)
ReverseCFGWorklist.push_back(*PI);
for (const auto Pred : children<Inverse<BlockT*>>(PredBB)) {
if (LI->getLoopFor(Pred) != Subloop)
ReverseCFGWorklist.push_back(Pred);
}
}
}
@ -482,13 +461,7 @@ analyze(const DominatorTreeBase<BlockT> &DomTree) {
SmallVector<BlockT *, 4> Backedges;
// Check each predecessor of the potential loop header.
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
for (typename InvBlockTraits::ChildIteratorType PI =
InvBlockTraits::child_begin(Header),
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
BlockT *Backedge = *PI;
for (const auto Backedge : children<Inverse<BlockT*>>(Header)) {
// If Header dominates predBB, this is a new loop. Collect the backedges.
if (DomTree.dominates(Header, Backedge)
&& DomTree.isReachableFromEntry(Backedge)) {

View File

@ -53,6 +53,11 @@ bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory similar to malloc or calloc.
bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast = false);
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,

View File

@ -1159,8 +1159,20 @@ class ScalarEvolution {
const SCEV *getConstant(const APInt &Val);
const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty);
typedef SmallDenseMap<std::pair<const SCEV *, Type *>, const SCEV *, 8>
ExtendCacheTy;
const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getZeroExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getSignExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getSignExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,

View File

@ -46,6 +46,9 @@ namespace llvm {
ArrayRef<uint8_t> Buffer;
StringRef ModuleIdentifier;
// The string table used to interpret this module.
StringRef Strtab;
// The bitstream location of the IDENTIFICATION_BLOCK.
uint64_t IdentificationBit;
@ -70,6 +73,7 @@ namespace llvm {
StringRef getBuffer() const {
return StringRef((const char *)Buffer.begin(), Buffer.size());
}
StringRef getStrtab() const { return Strtab; }
StringRef getModuleIdentifier() const { return ModuleIdentifier; }

View File

@ -15,6 +15,7 @@
#define LLVM_BITCODE_BITCODEWRITER_H
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/MC/StringTableBuilder.h"
#include <string>
namespace llvm {
@ -26,12 +27,25 @@ namespace llvm {
SmallVectorImpl<char> &Buffer;
std::unique_ptr<BitstreamWriter> Stream;
StringTableBuilder StrtabBuilder{StringTableBuilder::RAW};
bool WroteStrtab = false;
void writeBlob(unsigned Block, unsigned Record, StringRef Blob);
public:
/// Create a BitcodeWriter that writes to Buffer.
BitcodeWriter(SmallVectorImpl<char> &Buffer);
~BitcodeWriter();
/// Write the bitcode file's string table. This must be called exactly once
/// after all modules have been written.
void writeStrtab();
/// Copy the string table for another module into this bitcode file. This
/// should be called after copying the module itself into the bitcode file.
void copyStrtab(StringRef Strtab);
/// Write the specified module to the buffer specified at construction time.
///
/// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a

View File

@ -22,7 +22,7 @@
namespace llvm {
namespace bitc {
// The only top-level block type defined is for a module.
// The only top-level block types are MODULE, IDENTIFICATION and STRTAB.
enum BlockIDs {
// Blocks
MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID,
@ -52,7 +52,9 @@ enum BlockIDs {
OPERAND_BUNDLE_TAGS_BLOCK_ID,
METADATA_KIND_BLOCK_ID
METADATA_KIND_BLOCK_ID,
STRTAB_BLOCK_ID,
};
/// Identification block contains a string that describes the producer details,
@ -232,6 +234,10 @@ enum GlobalValueSummarySymtabCodes {
// llvm.type.checked.load intrinsic with all constant integer arguments.
// [typeid, offset, n x arg]
FS_TYPE_CHECKED_LOAD_CONST_VCALL = 15,
// Assigns a GUID to a value ID. This normally appears only in combined
// summaries, but it can also appear in per-module summaries for PGO data.
// [valueid, guid]
FS_VALUE_GUID = 16,
};
enum MetadataCodes {
@ -550,6 +556,10 @@ enum ComdatSelectionKindCodes {
COMDAT_SELECTION_KIND_SAME_SIZE = 5,
};
enum StrtabCodes {
STRTAB_BLOB = 1,
};
} // End bitc namespace
} // End llvm namespace

View File

@ -62,9 +62,6 @@ class InstructionSelector {
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const;
Optional<int64_t> getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI) const;
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const;

View File

@ -60,5 +60,8 @@ void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
const char *PassName, StringRef Msg,
const MachineInstr &MI);
Optional<int64_t> getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI);
} // End namespace llvm.
#endif

View File

@ -413,6 +413,11 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
unsigned Reg, unsigned Offset,
const MDNode *Variable, const MDNode *Expr);
/// Clone a DBG_VALUE whose value has been spilled to FrameIndex.
MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig, int FrameIndex);
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
}

View File

@ -28,155 +28,246 @@ namespace llvm {
/// type can be represented by an MVT.
class MVT {
public:
enum SimpleValueType : int8_t {
// Simple value types less than zero are considered extended value types.
INVALID_SIMPLE_VALUE_TYPE = -1,
enum SimpleValueType : uint8_t {
// Simple value types that aren't explicitly part of this enumeration
// are considered extended value types.
INVALID_SIMPLE_VALUE_TYPE = 0,
// If you change this numbering, you must change the values in
// ValueTypes.td as well!
Other = 0, // This is a non-standard value
i1 = 1, // This is a 1 bit integer value
i8 = 2, // This is an 8 bit integer value
i16 = 3, // This is a 16 bit integer value
i32 = 4, // This is a 32 bit integer value
i64 = 5, // This is a 64 bit integer value
i128 = 6, // This is a 128 bit integer value
Other = 1, // This is a non-standard value
i1 = 2, // This is a 1 bit integer value
i8 = 3, // This is an 8 bit integer value
i16 = 4, // This is a 16 bit integer value
i32 = 5, // This is a 32 bit integer value
i64 = 6, // This is a 64 bit integer value
i128 = 7, // This is a 128 bit integer value
FIRST_INTEGER_VALUETYPE = i1,
LAST_INTEGER_VALUETYPE = i128,
f16 = 7, // This is a 16 bit floating point value
f32 = 8, // This is a 32 bit floating point value
f64 = 9, // This is a 64 bit floating point value
f80 = 10, // This is a 80 bit floating point value
f128 = 11, // This is a 128 bit floating point value
ppcf128 = 12, // This is a PPC 128-bit floating point value
f16 = 8, // This is a 16 bit floating point value
f32 = 9, // This is a 32 bit floating point value
f64 = 10, // This is a 64 bit floating point value
f80 = 11, // This is a 80 bit floating point value
f128 = 12, // This is a 128 bit floating point value
ppcf128 = 13, // This is a PPC 128-bit floating point value
FIRST_FP_VALUETYPE = f16,
LAST_FP_VALUETYPE = ppcf128,
v2i1 = 13, // 2 x i1
v4i1 = 14, // 4 x i1
v8i1 = 15, // 8 x i1
v16i1 = 16, // 16 x i1
v32i1 = 17, // 32 x i1
v64i1 = 18, // 64 x i1
v512i1 = 19, // 512 x i1
v1024i1 = 20, // 1024 x i1
v2i1 = 14, // 2 x i1
v4i1 = 15, // 4 x i1
v8i1 = 16, // 8 x i1
v16i1 = 17, // 16 x i1
v32i1 = 18, // 32 x i1
v64i1 = 19, // 64 x i1
v512i1 = 20, // 512 x i1
v1024i1 = 21, // 1024 x i1
v1i8 = 21, // 1 x i8
v2i8 = 22, // 2 x i8
v4i8 = 23, // 4 x i8
v8i8 = 24, // 8 x i8
v16i8 = 25, // 16 x i8
v32i8 = 26, // 32 x i8
v64i8 = 27, // 64 x i8
v128i8 = 28, //128 x i8
v256i8 = 29, //256 x i8
v1i8 = 22, // 1 x i8
v2i8 = 23, // 2 x i8
v4i8 = 24, // 4 x i8
v8i8 = 25, // 8 x i8
v16i8 = 26, // 16 x i8
v32i8 = 27, // 32 x i8
v64i8 = 28, // 64 x i8
v128i8 = 29, //128 x i8
v256i8 = 30, //256 x i8
v1i16 = 30, // 1 x i16
v2i16 = 31, // 2 x i16
v4i16 = 32, // 4 x i16
v8i16 = 33, // 8 x i16
v16i16 = 34, // 16 x i16
v32i16 = 35, // 32 x i16
v64i16 = 36, // 64 x i16
v128i16 = 37, //128 x i16
v1i16 = 31, // 1 x i16
v2i16 = 32, // 2 x i16
v4i16 = 33, // 4 x i16
v8i16 = 34, // 8 x i16
v16i16 = 35, // 16 x i16
v32i16 = 36, // 32 x i16
v64i16 = 37, // 64 x i16
v128i16 = 38, //128 x i16
v1i32 = 38, // 1 x i32
v2i32 = 39, // 2 x i32
v4i32 = 40, // 4 x i32
v8i32 = 41, // 8 x i32
v16i32 = 42, // 16 x i32
v32i32 = 43, // 32 x i32
v64i32 = 44, // 64 x i32
v1i32 = 39, // 1 x i32
v2i32 = 40, // 2 x i32
v4i32 = 41, // 4 x i32
v8i32 = 42, // 8 x i32
v16i32 = 43, // 16 x i32
v32i32 = 44, // 32 x i32
v64i32 = 45, // 64 x i32
v1i64 = 45, // 1 x i64
v2i64 = 46, // 2 x i64
v4i64 = 47, // 4 x i64
v8i64 = 48, // 8 x i64
v16i64 = 49, // 16 x i64
v32i64 = 50, // 32 x i64
v1i64 = 46, // 1 x i64
v2i64 = 47, // 2 x i64
v4i64 = 48, // 4 x i64
v8i64 = 49, // 8 x i64
v16i64 = 50, // 16 x i64
v32i64 = 51, // 32 x i64
v1i128 = 51, // 1 x i128
v1i128 = 52, // 1 x i128
// Scalable integer types
nxv2i1 = 53, // n x 2 x i1
nxv4i1 = 54, // n x 4 x i1
nxv8i1 = 55, // n x 8 x i1
nxv16i1 = 56, // n x 16 x i1
nxv32i1 = 57, // n x 32 x i1
nxv1i8 = 58, // n x 1 x i8
nxv2i8 = 59, // n x 2 x i8
nxv4i8 = 60, // n x 4 x i8
nxv8i8 = 61, // n x 8 x i8
nxv16i8 = 62, // n x 16 x i8
nxv32i8 = 63, // n x 32 x i8
nxv1i16 = 64, // n x 1 x i16
nxv2i16 = 65, // n x 2 x i16
nxv4i16 = 66, // n x 4 x i16
nxv8i16 = 67, // n x 8 x i16
nxv16i16 = 68, // n x 16 x i16
nxv32i16 = 69, // n x 32 x i16
nxv1i32 = 70, // n x 1 x i32
nxv2i32 = 71, // n x 2 x i32
nxv4i32 = 72, // n x 4 x i32
nxv8i32 = 73, // n x 8 x i32
nxv16i32 = 74, // n x 16 x i32
nxv32i32 = 75, // n x 32 x i32
nxv1i64 = 76, // n x 1 x i64
nxv2i64 = 77, // n x 2 x i64
nxv4i64 = 78, // n x 4 x i64
nxv8i64 = 79, // n x 8 x i64
nxv16i64 = 80, // n x 16 x i64
nxv32i64 = 81, // n x 32 x i64
FIRST_INTEGER_VECTOR_VALUETYPE = v2i1,
LAST_INTEGER_VECTOR_VALUETYPE = v1i128,
LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64,
v2f16 = 52, // 2 x f16
v4f16 = 53, // 4 x f16
v8f16 = 54, // 8 x f16
v1f32 = 55, // 1 x f32
v2f32 = 56, // 2 x f32
v4f32 = 57, // 4 x f32
v8f32 = 58, // 8 x f32
v16f32 = 59, // 16 x f32
v1f64 = 60, // 1 x f64
v2f64 = 61, // 2 x f64
v4f64 = 62, // 4 x f64
v8f64 = 63, // 8 x f64
FIRST_INTEGER_SCALABLE_VALUETYPE = nxv2i1,
LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64,
v2f16 = 82, // 2 x f16
v4f16 = 83, // 4 x f16
v8f16 = 84, // 8 x f16
v1f32 = 85, // 1 x f32
v2f32 = 86, // 2 x f32
v4f32 = 87, // 4 x f32
v8f32 = 88, // 8 x f32
v16f32 = 89, // 16 x f32
v1f64 = 90, // 1 x f64
v2f64 = 91, // 2 x f64
v4f64 = 92, // 4 x f64
v8f64 = 93, // 8 x f64
nxv2f16 = 94, // n x 2 x f16
nxv4f16 = 95, // n x 4 x f16
nxv8f16 = 96, // n x 8 x f16
nxv1f32 = 97, // n x 1 x f32
nxv2f32 = 98, // n x 2 x f32
nxv4f32 = 99, // n x 4 x f32
nxv8f32 = 100, // n x 8 x f32
nxv16f32 = 101, // n x 16 x f32
nxv1f64 = 102, // n x 1 x f64
nxv2f64 = 103, // n x 2 x f64
nxv4f64 = 104, // n x 4 x f64
nxv8f64 = 105, // n x 8 x f64
FIRST_FP_VECTOR_VALUETYPE = v2f16,
LAST_FP_VECTOR_VALUETYPE = v8f64,
LAST_FP_VECTOR_VALUETYPE = nxv8f64,
FIRST_FP_SCALABLE_VALUETYPE = nxv2f16,
LAST_FP_SCALABLE_VALUETYPE = nxv8f64,
FIRST_VECTOR_VALUETYPE = v2i1,
LAST_VECTOR_VALUETYPE = v8f64,
LAST_VECTOR_VALUETYPE = nxv8f64,
x86mmx = 64, // This is an X86 MMX value
x86mmx = 106, // This is an X86 MMX value
Glue = 65, // This glues nodes together during pre-RA sched
Glue = 107, // This glues nodes together during pre-RA sched
isVoid = 66, // This has no value
isVoid = 108, // This has no value
Untyped = 67, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.
Untyped = 109, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.
FIRST_VALUETYPE = 0, // This is always the beginning of the list.
LAST_VALUETYPE = 68, // This always remains at the end of the list.
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
LAST_VALUETYPE = 110, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
// This value must be a multiple of 32.
MAX_ALLOWED_VALUETYPE = 96,
MAX_ALLOWED_VALUETYPE = 128,
// A value of type llvm::TokenTy
token = 120,
token = 248,
// This is MDNode or MDString.
Metadata = 121,
Metadata = 249,
// An int value the size of the pointer of the current
// target to any address space. This must only be used internal to
// tblgen. Other than for overloading, we treat iPTRAny the same as iPTR.
iPTRAny = 122,
iPTRAny = 250,
// A vector with any length and element size. This is used
// for intrinsics that have overloadings based on vector types.
// This is only for tblgen's consumption!
vAny = 123,
vAny = 251,
// Any floating-point or vector floating-point value. This is used
// for intrinsics that have overloadings based on floating-point types.
// This is only for tblgen's consumption!
fAny = 124,
fAny = 252,
// An integer or vector integer value of any bit width. This is
// used for intrinsics that have overloadings based on integer bit widths.
// This is only for tblgen's consumption!
iAny = 125,
iAny = 253,
// An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
iPTR = 126,
iPTR = 254,
// Any type. This is used for intrinsics that have overloadings.
// This is only for tblgen's consumption!
Any = 127
Any = 255
};
SimpleValueType SimpleTy;
// A class to represent the number of elements in a vector
//
// For fixed-length vectors, the total number of elements is equal to 'Min'
// For scalable vectors, the total number of elements is a multiple of 'Min'
class ElementCount {
public:
unsigned Min;
bool Scalable;
ElementCount(unsigned Min, bool Scalable)
: Min(Min), Scalable(Scalable) {}
ElementCount operator*(unsigned RHS) {
return { Min * RHS, Scalable };
}
ElementCount& operator*=(unsigned RHS) {
Min *= RHS;
return *this;
}
ElementCount operator/(unsigned RHS) {
return { Min / RHS, Scalable };
}
ElementCount& operator/=(unsigned RHS) {
Min /= RHS;
return *this;
}
bool operator==(const ElementCount& RHS) {
return Min == RHS.Min && Scalable == RHS.Scalable;
}
};
constexpr MVT() : SimpleTy(INVALID_SIMPLE_VALUE_TYPE) {}
constexpr MVT(SimpleValueType SVT) : SimpleTy(SVT) {}
@ -221,6 +312,15 @@ class MVT {
SimpleTy <= MVT::LAST_VECTOR_VALUETYPE);
}
/// Return true if this is a vector value type where the
/// runtime length is machine dependent
bool isScalableVector() const {
return ((SimpleTy >= MVT::FIRST_INTEGER_SCALABLE_VALUETYPE &&
SimpleTy <= MVT::LAST_INTEGER_SCALABLE_VALUETYPE) ||
(SimpleTy >= MVT::FIRST_FP_SCALABLE_VALUETYPE &&
SimpleTy <= MVT::LAST_FP_SCALABLE_VALUETYPE));
}
/// Return true if this is a 16-bit vector type.
bool is16BitVector() const {
return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 ||
@ -318,7 +418,12 @@ class MVT {
case v32i1:
case v64i1:
case v512i1:
case v1024i1: return i1;
case v1024i1:
case nxv2i1:
case nxv4i1:
case nxv8i1:
case nxv16i1:
case nxv32i1: return i1;
case v1i8:
case v2i8:
case v4i8:
@ -327,7 +432,13 @@ class MVT {
case v32i8:
case v64i8:
case v128i8:
case v256i8: return i8;
case v256i8:
case nxv1i8:
case nxv2i8:
case nxv4i8:
case nxv8i8:
case nxv16i8:
case nxv32i8: return i8;
case v1i16:
case v2i16:
case v4i16:
@ -335,33 +446,63 @@ class MVT {
case v16i16:
case v32i16:
case v64i16:
case v128i16: return i16;
case v128i16:
case nxv1i16:
case nxv2i16:
case nxv4i16:
case nxv8i16:
case nxv16i16:
case nxv32i16: return i16;
case v1i32:
case v2i32:
case v4i32:
case v8i32:
case v16i32:
case v32i32:
case v64i32: return i32;
case v64i32:
case nxv1i32:
case nxv2i32:
case nxv4i32:
case nxv8i32:
case nxv16i32:
case nxv32i32: return i32;
case v1i64:
case v2i64:
case v4i64:
case v8i64:
case v16i64:
case v32i64: return i64;
case v32i64:
case nxv1i64:
case nxv2i64:
case nxv4i64:
case nxv8i64:
case nxv16i64:
case nxv32i64: return i64;
case v1i128: return i128;
case v2f16:
case v4f16:
case v8f16: return f16;
case v8f16:
case nxv2f16:
case nxv4f16:
case nxv8f16: return f16;
case v1f32:
case v2f32:
case v4f32:
case v8f32:
case v16f32: return f32;
case v16f32:
case nxv1f32:
case nxv2f32:
case nxv4f32:
case nxv8f32:
case nxv16f32: return f32;
case v1f64:
case v2f64:
case v4f64:
case v8f64: return f64;
case v8f64:
case nxv1f64:
case nxv2f64:
case nxv4f64:
case nxv8f64: return f64;
}
}
@ -382,13 +523,24 @@ class MVT {
case v32i8:
case v32i16:
case v32i32:
case v32i64: return 32;
case v32i64:
case nxv32i1:
case nxv32i8:
case nxv32i16:
case nxv32i32:
case nxv32i64: return 32;
case v16i1:
case v16i8:
case v16i16:
case v16i32:
case v16i64:
case v16f32: return 16;
case v16f32:
case nxv16i1:
case nxv16i8:
case nxv16i16:
case nxv16i32:
case nxv16i64:
case nxv16f32: return 16;
case v8i1:
case v8i8:
case v8i16:
@ -396,7 +548,15 @@ class MVT {
case v8i64:
case v8f16:
case v8f32:
case v8f64: return 8;
case v8f64:
case nxv8i1:
case nxv8i8:
case nxv8i16:
case nxv8i32:
case nxv8i64:
case nxv8f16:
case nxv8f32:
case nxv8f64: return 8;
case v4i1:
case v4i8:
case v4i16:
@ -404,7 +564,15 @@ class MVT {
case v4i64:
case v4f16:
case v4f32:
case v4f64: return 4;
case v4f64:
case nxv4i1:
case nxv4i8:
case nxv4i16:
case nxv4i32:
case nxv4i64:
case nxv4f16:
case nxv4f32:
case nxv4f64: return 4;
case v2i1:
case v2i8:
case v2i16:
@ -412,17 +580,35 @@ class MVT {
case v2i64:
case v2f16:
case v2f32:
case v2f64: return 2;
case v2f64:
case nxv2i1:
case nxv2i8:
case nxv2i16:
case nxv2i32:
case nxv2i64:
case nxv2f16:
case nxv2f32:
case nxv2f64: return 2;
case v1i8:
case v1i16:
case v1i32:
case v1i64:
case v1i128:
case v1f32:
case v1f64: return 1;
case v1f64:
case nxv1i8:
case nxv1i16:
case nxv1i32:
case nxv1i64:
case nxv1f32:
case nxv1f64: return 1;
}
}
MVT::ElementCount getVectorElementCount() const {
return { getVectorNumElements(), isScalableVector() };
}
unsigned getSizeInBits() const {
switch (SimpleTy) {
default:
@ -443,16 +629,23 @@ class MVT {
case Metadata:
llvm_unreachable("Value type is metadata.");
case i1 : return 1;
case v2i1: return 2;
case v4i1: return 4;
case v2i1:
case nxv2i1: return 2;
case v4i1:
case nxv4i1: return 4;
case i8 :
case v1i8:
case v8i1: return 8;
case v8i1:
case nxv1i8:
case nxv8i1: return 8;
case i16 :
case f16:
case v16i1:
case v2i8:
case v1i16: return 16;
case v1i16:
case nxv16i1:
case nxv2i8:
case nxv1i16: return 16;
case f32 :
case i32 :
case v32i1:
@ -460,7 +653,13 @@ class MVT {
case v2i16:
case v2f16:
case v1f32:
case v1i32: return 32;
case v1i32:
case nxv32i1:
case nxv4i8:
case nxv2i16:
case nxv1i32:
case nxv2f16:
case nxv1f32: return 32;
case x86mmx:
case f64 :
case i64 :
@ -471,7 +670,14 @@ class MVT {
case v1i64:
case v4f16:
case v2f32:
case v1f64: return 64;
case v1f64:
case nxv8i8:
case nxv4i16:
case nxv2i32:
case nxv1i64:
case nxv4f16:
case nxv2f32:
case nxv1f64: return 64;
case f80 : return 80;
case f128:
case ppcf128:
@ -483,29 +689,50 @@ class MVT {
case v1i128:
case v8f16:
case v4f32:
case v2f64: return 128;
case v2f64:
case nxv16i8:
case nxv8i16:
case nxv4i32:
case nxv2i64:
case nxv8f16:
case nxv4f32:
case nxv2f64: return 128;
case v32i8:
case v16i16:
case v8i32:
case v4i64:
case v8f32:
case v4f64: return 256;
case v4f64:
case nxv32i8:
case nxv16i16:
case nxv8i32:
case nxv4i64:
case nxv8f32:
case nxv4f64: return 256;
case v512i1:
case v64i8:
case v32i16:
case v16i32:
case v8i64:
case v16f32:
case v8f64: return 512;
case v8f64:
case nxv32i16:
case nxv16i32:
case nxv8i64:
case nxv16f32:
case nxv8f64: return 512;
case v1024i1:
case v128i8:
case v64i16:
case v32i32:
case v16i64: return 1024;
case v16i64:
case nxv32i32:
case nxv16i64: return 1024;
case v256i8:
case v128i16:
case v64i32:
case v32i64: return 2048;
case v32i64:
case nxv32i64: return 2048;
}
}
@ -659,6 +886,83 @@ class MVT {
return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
}
static MVT getScalableVectorVT(MVT VT, unsigned NumElements) {
switch(VT.SimpleTy) {
default:
break;
case MVT::i1:
if (NumElements == 2) return MVT::nxv2i1;
if (NumElements == 4) return MVT::nxv4i1;
if (NumElements == 8) return MVT::nxv8i1;
if (NumElements == 16) return MVT::nxv16i1;
if (NumElements == 32) return MVT::nxv32i1;
break;
case MVT::i8:
if (NumElements == 1) return MVT::nxv1i8;
if (NumElements == 2) return MVT::nxv2i8;
if (NumElements == 4) return MVT::nxv4i8;
if (NumElements == 8) return MVT::nxv8i8;
if (NumElements == 16) return MVT::nxv16i8;
if (NumElements == 32) return MVT::nxv32i8;
break;
case MVT::i16:
if (NumElements == 1) return MVT::nxv1i16;
if (NumElements == 2) return MVT::nxv2i16;
if (NumElements == 4) return MVT::nxv4i16;
if (NumElements == 8) return MVT::nxv8i16;
if (NumElements == 16) return MVT::nxv16i16;
if (NumElements == 32) return MVT::nxv32i16;
break;
case MVT::i32:
if (NumElements == 1) return MVT::nxv1i32;
if (NumElements == 2) return MVT::nxv2i32;
if (NumElements == 4) return MVT::nxv4i32;
if (NumElements == 8) return MVT::nxv8i32;
if (NumElements == 16) return MVT::nxv16i32;
if (NumElements == 32) return MVT::nxv32i32;
break;
case MVT::i64:
if (NumElements == 1) return MVT::nxv1i64;
if (NumElements == 2) return MVT::nxv2i64;
if (NumElements == 4) return MVT::nxv4i64;
if (NumElements == 8) return MVT::nxv8i64;
if (NumElements == 16) return MVT::nxv16i64;
if (NumElements == 32) return MVT::nxv32i64;
break;
case MVT::f16:
if (NumElements == 2) return MVT::nxv2f16;
if (NumElements == 4) return MVT::nxv4f16;
if (NumElements == 8) return MVT::nxv8f16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::nxv1f32;
if (NumElements == 2) return MVT::nxv2f32;
if (NumElements == 4) return MVT::nxv4f32;
if (NumElements == 8) return MVT::nxv8f32;
if (NumElements == 16) return MVT::nxv16f32;
break;
case MVT::f64:
if (NumElements == 1) return MVT::nxv1f64;
if (NumElements == 2) return MVT::nxv2f64;
if (NumElements == 4) return MVT::nxv4f64;
if (NumElements == 8) return MVT::nxv8f64;
break;
}
return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
}
static MVT getVectorVT(MVT VT, unsigned NumElements, bool IsScalable) {
if (IsScalable)
return getScalableVectorVT(VT, NumElements);
return getVectorVT(VT, NumElements);
}
static MVT getVectorVT(MVT VT, MVT::ElementCount EC) {
if (EC.Scalable)
return getScalableVectorVT(VT, EC.Min);
return getVectorVT(VT, EC.Min);
}
/// Return the value type corresponding to the specified type. This returns
/// all pointers as iPTR. If HandleUnknown is true, unknown types are
/// returned as Other, otherwise they are invalid.
@ -709,6 +1013,14 @@ class MVT {
MVT::FIRST_FP_VECTOR_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1));
}
static mvt_range integer_scalable_vector_valuetypes() {
return mvt_range(MVT::FIRST_INTEGER_SCALABLE_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_INTEGER_SCALABLE_VALUETYPE + 1));
}
static mvt_range fp_scalable_vector_valuetypes() {
return mvt_range(MVT::FIRST_FP_SCALABLE_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_FP_SCALABLE_VALUETYPE + 1));
}
/// @}
};

View File

@ -44,7 +44,7 @@ namespace llvm {
bool operator!=(EVT VT) const {
if (V.SimpleTy != VT.V.SimpleTy)
return true;
if (V.SimpleTy < 0)
if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
return LLVMTy != VT.LLVMTy;
return false;
}
@ -60,31 +60,48 @@ namespace llvm {
/// bits.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) {
MVT M = MVT::getIntegerVT(BitWidth);
if (M.SimpleTy >= 0)
if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE)
return M;
return getExtendedIntegerVT(Context, BitWidth);
}
/// Returns the EVT that represents a vector NumElements in length, where
/// each element is of type VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) {
MVT M = MVT::getVectorVT(VT.V, NumElements);
if (M.SimpleTy >= 0)
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements,
bool IsScalable = false) {
MVT M = MVT::getVectorVT(VT.V, NumElements, IsScalable);
if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE)
return M;
assert(!IsScalable && "We don't support extended scalable types yet");
return getExtendedVectorVT(Context, VT, NumElements);
}
/// Returns the EVT that represents a vector EC.Min elements in length,
/// where each element is of type VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, MVT::ElementCount EC) {
MVT M = MVT::getVectorVT(VT.V, EC);
if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE)
return M;
assert (!EC.Scalable && "We don't support extended scalable types yet");
return getExtendedVectorVT(Context, VT, EC.Min);
}
/// Return a vector with the same number of elements as this vector, but
/// with the element type converted to an integer type with the same
/// bitwidth.
EVT changeVectorElementTypeToInteger() const {
if (!isSimple())
if (!isSimple()) {
assert (!isScalableVector() &&
"We don't support extended scalable types yet");
return changeExtendedVectorElementTypeToInteger();
}
MVT EltTy = getSimpleVT().getVectorElementType();
unsigned BitWidth = EltTy.getSizeInBits();
MVT IntTy = MVT::getIntegerVT(BitWidth);
MVT VecTy = MVT::getVectorVT(IntTy, getVectorNumElements());
assert(VecTy.SimpleTy >= 0 &&
MVT VecTy = MVT::getVectorVT(IntTy, getVectorNumElements(),
isScalableVector());
assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE &&
"Simple vector VT not representable by simple integer vector VT!");
return VecTy;
}
@ -104,7 +121,7 @@ namespace llvm {
/// Test if the given EVT is simple (as opposed to being extended).
bool isSimple() const {
return V.SimpleTy >= 0;
return V.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE;
}
/// Test if the given EVT is extended (as opposed to being simple).
@ -132,6 +149,17 @@ namespace llvm {
return isSimple() ? V.isVector() : isExtendedVector();
}
/// Return true if this is a vector type where the runtime
/// length is machine dependent
bool isScalableVector() const {
// FIXME: We don't support extended scalable types yet, because the
// matching IR type doesn't exist. Once it has been added, this can
// be changed to call isExtendedScalableVector.
if (!isSimple())
return false;
return V.isScalableVector();
}
/// Return true if this is a 16-bit vector type.
bool is16BitVector() const {
return isSimple() ? V.is16BitVector() : isExtended16BitVector();
@ -247,6 +275,17 @@ namespace llvm {
return getExtendedVectorNumElements();
}
// Given a (possibly scalable) vector type, return the ElementCount
MVT::ElementCount getVectorElementCount() const {
assert((isVector()) && "Invalid vector type!");
if (isSimple())
return V.getVectorElementCount();
assert(!isScalableVector() &&
"We don't support extended scalable types yet");
return {getExtendedVectorNumElements(), false};
}
/// Return the size of the specified value type in bits.
unsigned getSizeInBits() const {
if (isSimple())
@ -301,7 +340,17 @@ namespace llvm {
EVT widenIntegerVectorElementType(LLVMContext &Context) const {
EVT EltVT = getVectorElementType();
EltVT = EVT::getIntegerVT(Context, 2 * EltVT.getSizeInBits());
return EVT::getVectorVT(Context, EltVT, getVectorNumElements());
return EVT::getVectorVT(Context, EltVT, getVectorElementCount());
}
// Return a VT for a vector type with the same element type but
// half the number of elements. The type returned may be an
// extended type.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const {
EVT EltVT = getVectorElementType();
auto EltCnt = getVectorElementCount();
assert(!(EltCnt.Min & 1) && "Splitting vector, but not in half!");
return EVT::getVectorVT(Context, EltVT, EltCnt / 2);
}
/// Returns true if the given vector is a power of 2.
@ -316,7 +365,8 @@ namespace llvm {
if (!isPow2VectorType()) {
unsigned NElts = getVectorNumElements();
unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts);
return EVT::getVectorVT(Context, getVectorElementType(), Pow2NElts);
return EVT::getVectorVT(Context, getVectorElementType(), Pow2NElts,
isScalableVector());
}
else {
return *this;

View File

@ -19,101 +19,147 @@ class ValueType<int size, int value> {
int Value = value;
}
def OtherVT: ValueType<0 , 0>; // "Other" value
def i1 : ValueType<1 , 1>; // One bit boolean value
def i8 : ValueType<8 , 2>; // 8-bit integer value
def i16 : ValueType<16 , 3>; // 16-bit integer value
def i32 : ValueType<32 , 4>; // 32-bit integer value
def i64 : ValueType<64 , 5>; // 64-bit integer value
def i128 : ValueType<128, 6>; // 128-bit integer value
def f16 : ValueType<16 , 7>; // 16-bit floating point value
def f32 : ValueType<32 , 8>; // 32-bit floating point value
def f64 : ValueType<64 , 9>; // 64-bit floating point value
def f80 : ValueType<80 , 10>; // 80-bit floating point value
def f128 : ValueType<128, 11>; // 128-bit floating point value
def ppcf128: ValueType<128, 12>; // PPC 128-bit floating point value
def OtherVT: ValueType<0 , 1>; // "Other" value
def i1 : ValueType<1 , 2>; // One bit boolean value
def i8 : ValueType<8 , 3>; // 8-bit integer value
def i16 : ValueType<16 , 4>; // 16-bit integer value
def i32 : ValueType<32 , 5>; // 32-bit integer value
def i64 : ValueType<64 , 6>; // 64-bit integer value
def i128 : ValueType<128, 7>; // 128-bit integer value
def f16 : ValueType<16 , 8>; // 16-bit floating point value
def f32 : ValueType<32 , 9>; // 32-bit floating point value
def f64 : ValueType<64 , 10>; // 64-bit floating point value
def f80 : ValueType<80 , 11>; // 80-bit floating point value
def f128 : ValueType<128, 12>; // 128-bit floating point value
def ppcf128: ValueType<128, 13>; // PPC 128-bit floating point value
def v2i1 : ValueType<2 , 13>; // 2 x i1 vector value
def v4i1 : ValueType<4 , 14>; // 4 x i1 vector value
def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value
def v16i1 : ValueType<16, 16>; // 16 x i1 vector value
def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value
def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value
def v512i1 : ValueType<512, 19>; // 512 x i1 vector value
def v1024i1: ValueType<1024,20>; //1024 x i1 vector value
def v2i1 : ValueType<2 , 14>; // 2 x i1 vector value
def v4i1 : ValueType<4 , 15>; // 4 x i1 vector value
def v8i1 : ValueType<8 , 16>; // 8 x i1 vector value
def v16i1 : ValueType<16, 17>; // 16 x i1 vector value
def v32i1 : ValueType<32 , 18>; // 32 x i1 vector value
def v64i1 : ValueType<64 , 19>; // 64 x i1 vector value
def v512i1 : ValueType<512, 20>; // 512 x i1 vector value
def v1024i1: ValueType<1024,21>; //1024 x i1 vector value
def v1i8 : ValueType<16, 21>; // 1 x i8 vector value
def v2i8 : ValueType<16 , 22>; // 2 x i8 vector value
def v4i8 : ValueType<32 , 23>; // 4 x i8 vector value
def v8i8 : ValueType<64 , 24>; // 8 x i8 vector value
def v16i8 : ValueType<128, 25>; // 16 x i8 vector value
def v32i8 : ValueType<256, 26>; // 32 x i8 vector value
def v64i8 : ValueType<512, 27>; // 64 x i8 vector value
def v128i8 : ValueType<1024,28>; //128 x i8 vector value
def v256i8 : ValueType<2048,29>; //256 x i8 vector value
def v1i8 : ValueType<16, 22>; // 1 x i8 vector value
def v2i8 : ValueType<16 , 23>; // 2 x i8 vector value
def v4i8 : ValueType<32 , 24>; // 4 x i8 vector value
def v8i8 : ValueType<64 , 25>; // 8 x i8 vector value
def v16i8 : ValueType<128, 26>; // 16 x i8 vector value
def v32i8 : ValueType<256, 27>; // 32 x i8 vector value
def v64i8 : ValueType<512, 28>; // 64 x i8 vector value
def v128i8 : ValueType<1024,29>; //128 x i8 vector value
def v256i8 : ValueType<2048,30>; //256 x i8 vector value
def v1i16 : ValueType<16 , 30>; // 1 x i16 vector value
def v2i16 : ValueType<32 , 31>; // 2 x i16 vector value
def v4i16 : ValueType<64 , 32>; // 4 x i16 vector value
def v8i16 : ValueType<128, 33>; // 8 x i16 vector value
def v16i16 : ValueType<256, 34>; // 16 x i16 vector value
def v32i16 : ValueType<512, 35>; // 32 x i16 vector value
def v64i16 : ValueType<1024,36>; // 64 x i16 vector value
def v128i16: ValueType<2048,37>; //128 x i16 vector value
def v1i16 : ValueType<16 , 31>; // 1 x i16 vector value
def v2i16 : ValueType<32 , 32>; // 2 x i16 vector value
def v4i16 : ValueType<64 , 33>; // 4 x i16 vector value
def v8i16 : ValueType<128, 34>; // 8 x i16 vector value
def v16i16 : ValueType<256, 35>; // 16 x i16 vector value
def v32i16 : ValueType<512, 36>; // 32 x i16 vector value
def v64i16 : ValueType<1024,37>; // 64 x i16 vector value
def v128i16: ValueType<2048,38>; //128 x i16 vector value
def v1i32 : ValueType<32 , 38>; // 1 x i32 vector value
def v2i32 : ValueType<64 , 39>; // 2 x i32 vector value
def v4i32 : ValueType<128, 40>; // 4 x i32 vector value
def v8i32 : ValueType<256, 41>; // 8 x i32 vector value
def v16i32 : ValueType<512, 42>; // 16 x i32 vector value
def v32i32 : ValueType<1024,43>; // 32 x i32 vector value
def v64i32 : ValueType<2048,44>; // 32 x i32 vector value
def v1i32 : ValueType<32 , 39>; // 1 x i32 vector value
def v2i32 : ValueType<64 , 40>; // 2 x i32 vector value
def v4i32 : ValueType<128, 41>; // 4 x i32 vector value
def v8i32 : ValueType<256, 42>; // 8 x i32 vector value
def v16i32 : ValueType<512, 43>; // 16 x i32 vector value
def v32i32 : ValueType<1024,44>; // 32 x i32 vector value
def v64i32 : ValueType<2048,45>; // 32 x i32 vector value
def v1i64 : ValueType<64 , 45>; // 1 x i64 vector value
def v2i64 : ValueType<128, 46>; // 2 x i64 vector value
def v4i64 : ValueType<256, 47>; // 4 x i64 vector value
def v8i64 : ValueType<512, 48>; // 8 x i64 vector value
def v16i64 : ValueType<1024,49>; // 16 x i64 vector value
def v32i64 : ValueType<2048,50>; // 32 x i64 vector value
def v1i64 : ValueType<64 , 46>; // 1 x i64 vector value
def v2i64 : ValueType<128, 47>; // 2 x i64 vector value
def v4i64 : ValueType<256, 48>; // 4 x i64 vector value
def v8i64 : ValueType<512, 49>; // 8 x i64 vector value
def v16i64 : ValueType<1024,50>; // 16 x i64 vector value
def v32i64 : ValueType<2048,51>; // 32 x i64 vector value
def v1i128 : ValueType<128, 51>; // 1 x i128 vector value
def v1i128 : ValueType<128, 52>; // 1 x i128 vector value
def v2f16 : ValueType<32 , 52>; // 2 x f16 vector value
def v4f16 : ValueType<64 , 53>; // 4 x f16 vector value
def v8f16 : ValueType<128, 54>; // 8 x f16 vector value
def v1f32 : ValueType<32 , 55>; // 1 x f32 vector value
def v2f32 : ValueType<64 , 56>; // 2 x f32 vector value
def v4f32 : ValueType<128, 57>; // 4 x f32 vector value
def v8f32 : ValueType<256, 58>; // 8 x f32 vector value
def v16f32 : ValueType<512, 59>; // 16 x f32 vector value
def v1f64 : ValueType<64, 60>; // 1 x f64 vector value
def v2f64 : ValueType<128, 61>; // 2 x f64 vector value
def v4f64 : ValueType<256, 62>; // 4 x f64 vector value
def v8f64 : ValueType<512, 63>; // 8 x f64 vector value
def nxv2i1 : ValueType<2, 53>; // n x 2 x i1 vector value
def nxv4i1 : ValueType<4, 54>; // n x 4 x i1 vector value
def nxv8i1 : ValueType<8, 55>; // n x 8 x i1 vector value
def nxv16i1 : ValueType<16, 56>; // n x 16 x i1 vector value
def nxv32i1 : ValueType<32, 57>; // n x 32 x i1 vector value
def nxv1i8 : ValueType<8, 58>; // n x 1 x i8 vector value
def nxv2i8 : ValueType<16, 59>; // n x 2 x i8 vector value
def nxv4i8 : ValueType<32, 60>; // n x 4 x i8 vector value
def nxv8i8 : ValueType<64, 61>; // n x 8 x i8 vector value
def nxv16i8 : ValueType<128, 62>; // n x 16 x i8 vector value
def nxv32i8 : ValueType<256, 63>; // n x 32 x i8 vector value
def x86mmx : ValueType<64 , 64>; // X86 MMX value
def FlagVT : ValueType<0 , 65>; // Pre-RA sched glue
def isVoid : ValueType<0 , 66>; // Produces no value
def untyped: ValueType<8 , 67>; // Produces an untyped value
def token : ValueType<0 , 120>; // TokenTy
def MetadataVT: ValueType<0, 121>; // Metadata
def nxv1i16 : ValueType<16, 64>; // n x 1 x i16 vector value
def nxv2i16 : ValueType<32, 65>; // n x 2 x i16 vector value
def nxv4i16 : ValueType<64, 66>; // n x 4 x i16 vector value
def nxv8i16 : ValueType<128, 67>; // n x 8 x i16 vector value
def nxv16i16: ValueType<256, 68>; // n x 16 x i16 vector value
def nxv32i16: ValueType<512, 69>; // n x 32 x i16 vector value
def nxv1i32 : ValueType<32, 70>; // n x 1 x i32 vector value
def nxv2i32 : ValueType<64, 71>; // n x 2 x i32 vector value
def nxv4i32 : ValueType<128, 72>; // n x 4 x i32 vector value
def nxv8i32 : ValueType<256, 73>; // n x 8 x i32 vector value
def nxv16i32: ValueType<512, 74>; // n x 16 x i32 vector value
def nxv32i32: ValueType<1024,75>; // n x 32 x i32 vector value
def nxv1i64 : ValueType<64, 76>; // n x 1 x i64 vector value
def nxv2i64 : ValueType<128, 77>; // n x 2 x i64 vector value
def nxv4i64 : ValueType<256, 78>; // n x 4 x i64 vector value
def nxv8i64 : ValueType<512, 79>; // n x 8 x i64 vector value
def nxv16i64: ValueType<1024,80>; // n x 16 x i64 vector value
def nxv32i64: ValueType<2048,81>; // n x 32 x i64 vector value
def v2f16 : ValueType<32 , 82>; // 2 x f16 vector value
def v4f16 : ValueType<64 , 83>; // 4 x f16 vector value
def v8f16 : ValueType<128, 84>; // 8 x f16 vector value
def v1f32 : ValueType<32 , 85>; // 1 x f32 vector value
def v2f32 : ValueType<64 , 86>; // 2 x f32 vector value
def v4f32 : ValueType<128, 87>; // 4 x f32 vector value
def v8f32 : ValueType<256, 88>; // 8 x f32 vector value
def v16f32 : ValueType<512, 89>; // 16 x f32 vector value
def v1f64 : ValueType<64, 90>; // 1 x f64 vector value
def v2f64 : ValueType<128, 91>; // 2 x f64 vector value
def v4f64 : ValueType<256, 92>; // 4 x f64 vector value
def v8f64 : ValueType<512, 93>; // 8 x f64 vector value
def nxv2f16 : ValueType<32 , 94>; // n x 2 x f16 vector value
def nxv4f16 : ValueType<64 , 95>; // n x 4 x f16 vector value
def nxv8f16 : ValueType<128, 96>; // n x 8 x f16 vector value
def nxv1f32 : ValueType<32 , 97>; // n x 1 x f32 vector value
def nxv2f32 : ValueType<64 , 98>; // n x 2 x f32 vector value
def nxv4f32 : ValueType<128, 99>; // n x 4 x f32 vector value
def nxv8f32 : ValueType<256, 100>; // n x 8 x f32 vector value
def nxv16f32 : ValueType<512, 101>; // n x 16 x f32 vector value
def nxv1f64 : ValueType<64, 102>; // n x 1 x f64 vector value
def nxv2f64 : ValueType<128, 103>; // n x 2 x f64 vector value
def nxv4f64 : ValueType<256, 104>; // n x 4 x f64 vector value
def nxv8f64 : ValueType<512, 105>; // n x 8 x f64 vector value
def x86mmx : ValueType<64 , 106>; // X86 MMX value
def FlagVT : ValueType<0 , 107>; // Pre-RA sched glue
def isVoid : ValueType<0 , 108>; // Produces no value
def untyped: ValueType<8 , 109>; // Produces an untyped value
def token : ValueType<0 , 248>; // TokenTy
def MetadataVT: ValueType<0, 249>; // Metadata
// Pseudo valuetype mapped to the current pointer size to any address space.
// Should only be used in TableGen.
def iPTRAny : ValueType<0, 122>;
def iPTRAny : ValueType<0, 250>;
// Pseudo valuetype to represent "vector of any size"
def vAny : ValueType<0 , 123>;
def vAny : ValueType<0 , 251>;
// Pseudo valuetype to represent "float of any format"
def fAny : ValueType<0 , 124>;
def fAny : ValueType<0 , 252>;
// Pseudo valuetype to represent "integer of any bit width"
def iAny : ValueType<0 , 125>;
def iAny : ValueType<0 , 253>;
// Pseudo valuetype mapped to the current pointer size.
def iPTR : ValueType<0 , 126>;
def iPTR : ValueType<0 , 254>;
// Pseudo valuetype to represent "any type of any size".
def Any : ValueType<0 , 127>;
def Any : ValueType<0 , 255>;

View File

@ -247,16 +247,11 @@ class DWARFDie {
/// DW_AT_call_line attribute in this DIE.
/// \param CallColumn filled in with non-zero if successful, zero if there is
/// no DW_AT_call_column attribute in this DIE.
/// \param CallDiscriminator filled in with non-zero if successful, zero if
/// there is no DW_AT_GNU_discriminator attribute in this DIE.
void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
uint32_t &CallColumn) const;
uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
/// Get inlined chain for a given address, rooted at the current DIE.
/// Returns empty chain if address is not contained in address range
/// of current DIE.
void
getInlinedChainForAddress(const uint64_t Address,
SmallVectorImpl<DWARFDie> &InlinedChain) const;
class attribute_iterator;
/// Get an iterator range to all attributes in the current DIE only.

View File

@ -31,6 +31,7 @@
#include <cstdint>
#include <memory>
#include <vector>
#include <map>
namespace llvm {
@ -134,6 +135,11 @@ class DWARFUnit {
uint64_t BaseAddr;
// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
// Map from range's start address to end address and corresponding DIE.
// IntervalMap does not support range removal, as a result, we use the
// std::map::upper_bound for address range lookup.
std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>
die_iterator_range;
@ -183,6 +189,9 @@ class DWARFUnit {
AddrOffsetSectionBase = Base;
}
// Recursively update address to Die map.
void updateAddressDieMap(DWARFDie Die);
void setRangesSection(StringRef RS, uint32_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
@ -339,10 +348,10 @@ class DWARFUnit {
/// it was actually constructed.
bool parseDWO();
/// getSubprogramForAddress - Returns subprogram DIE with address range
/// getSubroutineForAddress - Returns subprogram DIE with address range
/// encompassing the provided address. The pointer is alive as long as parsed
/// compile unit DIEs are not cleared.
DWARFDie getSubprogramForAddress(uint64_t Address);
DWARFDie getSubroutineForAddress(uint64_t Address);
};
} // end namespace llvm

View File

@ -108,18 +108,16 @@ class Argument : public Value {
bool hasSExtAttr() const;
/// Add attributes to an argument.
void addAttr(AttributeList AS);
void addAttrs(AttrBuilder &B);
void addAttr(Attribute::AttrKind Kind) {
addAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
void addAttr(Attribute::AttrKind Kind);
void addAttr(Attribute Attr);
/// Remove attributes from an argument.
void removeAttr(AttributeList AS);
void removeAttr(Attribute::AttrKind Kind) {
removeAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
void removeAttr(Attribute::AttrKind Kind);
/// Check if an argument has a given attribute.
bool hasAttribute(Attribute::AttrKind Kind) const;

View File

@ -356,9 +356,6 @@ class AttributeList {
AttributeList addAttributes(LLVMContext &C, unsigned Index,
AttributeList Attrs) const;
AttributeList addAttributes(LLVMContext &C, unsigned Index,
AttributeSet AS) const;
AttributeList addAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &B) const;

View File

@ -41,17 +41,14 @@ namespace llvm {
class MDNode;
/// This class represents a range of values.
///
class ConstantRange {
APInt Lower, Upper;
public:
/// Initialize a full (the default) or empty set for the specified bit width.
///
explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
/// Initialize a range to hold the single specified value.
///
ConstantRange(APInt Value);
/// @brief Initialize a range of values explicitly. This will assert out if
@ -119,46 +116,36 @@ class ConstantRange {
bool getEquivalentICmp(CmpInst::Predicate &Pred, APInt &RHS) const;
/// Return the lower value for this range.
///
const APInt &getLower() const { return Lower; }
/// Return the upper value for this range.
///
const APInt &getUpper() const { return Upper; }
/// Get the bit width of this ConstantRange.
///
uint32_t getBitWidth() const { return Lower.getBitWidth(); }
/// Return true if this set contains all of the elements possible
/// for this data-type.
///
bool isFullSet() const;
/// Return true if this set contains no members.
///
bool isEmptySet() const;
/// Return true if this set wraps around the top of the range.
/// For example: [100, 8).
///
bool isWrappedSet() const;
/// Return true if this set wraps around the INT_MIN of
/// its bitwidth. For example: i8 [120, 140).
///
bool isSignWrappedSet() const;
/// Return true if the specified value is in the set.
///
bool contains(const APInt &Val) const;
/// Return true if the other range is a subset of this one.
///
bool contains(const ConstantRange &CR) const;
/// If this set contains a single element, return it, otherwise return null.
///
const APInt *getSingleElement() const {
if (Upper == Lower + 1)
return &Lower;
@ -174,35 +161,27 @@ class ConstantRange {
}
/// Return true if this set contains exactly one member.
///
bool isSingleElement() const { return getSingleElement() != nullptr; }
/// Return the number of elements in this set.
///
APInt getSetSize() const;
/// Compare set size of this range with the range CR.
///
bool isSizeStrictlySmallerThanOf(const ConstantRange &CR) const;
/// Return the largest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMax() const;
/// Return the smallest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMin() const;
/// Return the largest signed value contained in the ConstantRange.
///
APInt getSignedMax() const;
/// Return the smallest signed value contained in the ConstantRange.
///
APInt getSignedMin() const;
/// Return true if this range is equal to another range.
///
bool operator==(const ConstantRange &CR) const {
return Lower == CR.Lower && Upper == CR.Upper;
}
@ -213,8 +192,8 @@ class ConstantRange {
/// Subtract the specified constant from the endpoints of this constant range.
ConstantRange subtract(const APInt &CI) const;
/// \brief Subtract the specified range from this range (aka relative
/// complement of the sets).
/// Subtract the specified range from this range (aka relative complement of
/// the sets).
ConstantRange difference(const ConstantRange &CR) const;
/// Return the range that results from the intersection of
@ -223,7 +202,6 @@ class ConstantRange {
/// smallest possible set size that does so. Because there may be two
/// intersections with the same set size, A.intersectWith(B) might not
/// be equal to B.intersectWith(A).
///
ConstantRange intersectWith(const ConstantRange &CR) const;
/// Return the range that results from the union of this range
@ -231,7 +209,6 @@ class ConstantRange {
/// elements of both sets, but may contain more. For example, [3, 9) union
/// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
/// in either set before.
///
ConstantRange unionWith(const ConstantRange &CR) const;
/// Return a new range representing the possible values resulting
@ -331,15 +308,12 @@ class ConstantRange {
ConstantRange lshr(const ConstantRange &Other) const;
/// Return a new range that is the logical not of the current set.
///
ConstantRange inverse() const;
/// Print out the bounds to a stream.
///
void print(raw_ostream &OS) const;
/// Allow printing from a debugger easily.
///
void dump() const;
};

View File

@ -778,6 +778,9 @@ namespace llvm {
}
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_ISA_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef)
} // end namespace llvm
#endif // LLVM_IR_DIBUILDER_H

View File

@ -2232,6 +2232,9 @@ class DIExpression : public MDNode {
expr_op_iterator expr_op_end() const {
return expr_op_iterator(elements_end());
}
iterator_range<expr_op_iterator> expr_ops() const {
return {expr_op_begin(), expr_op_end()};
}
/// @}
bool isValid() const;
@ -2240,7 +2243,7 @@ class DIExpression : public MDNode {
return MD->getMetadataID() == DIExpressionKind;
}
/// Is the first element a DW_OP_deref?.
/// Return whether the first element a DW_OP_deref.
bool startsWithDeref() const {
return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref;
}

View File

@ -273,10 +273,11 @@ class LoadInst : public UnaryInstruction {
Value *getPointerOperand() { return getOperand(0); }
const Value *getPointerOperand() const { return getOperand(0); }
static unsigned getPointerOperandIndex() { return 0U; }
Type *getPointerOperandType() const { return getPointerOperand()->getType(); }
/// Returns the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return getPointerOperand()->getType()->getPointerAddressSpace();
return getPointerOperandType()->getPointerAddressSpace();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -397,10 +398,11 @@ class StoreInst : public Instruction {
Value *getPointerOperand() { return getOperand(1); }
const Value *getPointerOperand() const { return getOperand(1); }
static unsigned getPointerOperandIndex() { return 1U; }
Type *getPointerOperandType() const { return getPointerOperand()->getType(); }
/// Returns the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return getPointerOperand()->getType()->getPointerAddressSpace();
return getPointerOperandType()->getPointerAddressSpace();
}
// Methods for support type inquiry through isa, cast, and dyn_cast:

View File

@ -30,6 +30,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstddef>
@ -133,6 +134,14 @@ class Metadata {
/// @}
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
// Specialized opaque metadata conversions.
inline Metadata **unwrap(LLVMMetadataRef *MDs) {
return reinterpret_cast<Metadata**>(MDs);
}
#define HANDLE_METADATA(CLASS) class CLASS;
#include "llvm/IR/Metadata.def"

View File

@ -160,7 +160,6 @@ class GlobalValueSummary {
std::vector<ValueInfo> RefEdgeList;
protected:
/// GlobalValueSummary constructor.
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
: Kind(K), Flags(Flags), OriginalName(0), RefEdgeList(std::move(Refs)) {}
@ -221,7 +220,6 @@ class AliasSummary : public GlobalValueSummary {
GlobalValueSummary *AliaseeSummary;
public:
/// Summary constructors.
AliasSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
: GlobalValueSummary(AliasKind, Flags, std::move(Refs)) {}
@ -297,7 +295,6 @@ class FunctionSummary : public GlobalValueSummary {
std::unique_ptr<TypeIdInfo> TIdInfo;
public:
/// Summary constructors.
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
std::vector<EdgeTy> CGEdges,
std::vector<GlobalValue::GUID> TypeTests,
@ -418,7 +415,6 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
class GlobalVarSummary : public GlobalValueSummary {
public:
/// Summary constructors.
GlobalVarSummary(GVFlags Flags, std::vector<ValueInfo> Refs)
: GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)) {}

View File

@ -267,15 +267,15 @@ inline cst_pred_ty<is_all_ones> m_AllOnes() {
}
inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; }
struct is_sign_bit {
bool isValue(const APInt &C) { return C.isSignBit(); }
struct is_sign_mask {
bool isValue(const APInt &C) { return C.isSignMask(); }
};
/// \brief Match an integer or vector with only the sign bit(s) set.
inline cst_pred_ty<is_sign_bit> m_SignBit() {
return cst_pred_ty<is_sign_bit>();
inline cst_pred_ty<is_sign_mask> m_SignMask() {
return cst_pred_ty<is_sign_mask>();
}
inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; }
inline api_pred_ty<is_sign_mask> m_SignMask(const APInt *&V) { return V; }
struct is_power2 {
bool isValue(const APInt &C) { return C.isPowerOf2(); }

View File

@ -61,9 +61,29 @@ class Use {
/// that also works with less standard-compliant compilers
void swap(Use &RHS);
/// Pointer traits for the UserRef PointerIntPair. This ensures we always
/// use the LSB regardless of pointer alignment on different targets.
struct UserRefPointerTraits {
static inline void *getAsVoidPointer(User *P) { return P; }
static inline User *getFromVoidPointer(void *P) {
return (User *)P;
}
enum { NumLowBitsAvailable = 1 };
};
// A type for the word following an array of hung-off Uses in memory, which is
// a pointer back to their User with the bottom bit set.
typedef PointerIntPair<User *, 1, unsigned> UserRef;
typedef PointerIntPair<User *, 1, unsigned, UserRefPointerTraits> UserRef;
/// Pointer traits for the Prev PointerIntPair. This ensures we always use
/// the two LSBs regardless of pointer alignment on different targets.
struct PrevPointerTraits {
static inline void *getAsVoidPointer(Use **P) { return P; }
static inline Use **getFromVoidPointer(void *P) {
return (Use **)P;
}
enum { NumLowBitsAvailable = 2 };
};
private:
/// Destructor - Only for zap()
@ -115,7 +135,7 @@ class Use {
Value *Val;
Use *Next;
PointerIntPair<Use **, 2, PrevPtrTag> Prev;
PointerIntPair<Use **, 2, PrevPtrTag, PrevPointerTraits> Prev;
void setPrev(Use **NewPrev) { Prev.setPointer(NewPrev); }

View File

@ -65,8 +65,8 @@ class MCAsmInfo {
// Properties to be set by the target writer, used to configure asm printer.
//
/// Pointer size in bytes. Default is 4.
unsigned PointerSize = 4;
/// Code pointer size in bytes. Default is 4.
unsigned CodePointerSize = 4;
/// Size of the stack slot reserved for callee-saved registers, in bytes.
/// Default is same as pointer size.
@ -384,8 +384,8 @@ class MCAsmInfo {
explicit MCAsmInfo();
virtual ~MCAsmInfo();
/// Get the pointer size in bytes.
unsigned getPointerSize() const { return PointerSize; }
/// Get the code pointer size in bytes.
unsigned getCodePointerSize() const { return CodePointerSize; }
/// Get the callee-saved register stack slot
/// size in bytes.

View File

@ -128,6 +128,7 @@ class ARMTargetStreamer : public MCTargetStreamer {
virtual void emitArch(unsigned Arch);
virtual void emitArchExtension(unsigned ArchExt);
virtual void emitObjectArch(unsigned Arch);
void emitTargetAttributes(const MCSubtargetInfo &STI);
virtual void finishAttributeSection();
virtual void emitInst(uint32_t Inst, char Suffix = '\0');

View File

@ -86,6 +86,10 @@ class MCSubtargetInfo {
FeatureBits = FeatureBits_;
}
bool hasFeature(unsigned Feature) const {
return FeatureBits[Feature];
}
protected:
/// Initialize the scheduling model and feature bits.
///

View File

@ -14,15 +14,20 @@
#ifndef LLVM_OBJECT_ARCHIVE_H
#define LLVM_OBJECT_ARCHIVE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
namespace llvm {
namespace object {
@ -32,25 +37,28 @@ class Archive;
class ArchiveMemberHeader {
public:
friend class Archive;
ArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
uint64_t Size, Error *Err);
// ArchiveMemberHeader() = default;
/// Get the name without looking up long names.
Expected<llvm::StringRef> getRawName() const;
Expected<StringRef> getRawName() const;
/// Get the name looking up long names.
Expected<llvm::StringRef> getName(uint64_t Size) const;
Expected<StringRef> getName(uint64_t Size) const;
/// Members are not larger than 4GB.
Expected<uint32_t> getSize() const;
Expected<sys::fs::perms> getAccessMode() const;
Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
llvm::StringRef getRawLastModified() const {
StringRef getRawLastModified() const {
return StringRef(ArMemHdr->LastModified,
sizeof(ArMemHdr->LastModified)).rtrim(' ');
}
Expected<unsigned> getUID() const;
Expected<unsigned> getGID() const;
@ -75,11 +83,13 @@ class ArchiveMemberHeader {
class Archive : public Binary {
virtual void anchor();
public:
class Child {
friend Archive;
const Archive *Parent;
friend ArchiveMemberHeader;
const Archive *Parent;
ArchiveMemberHeader Header;
/// \brief Includes header but not padding byte.
StringRef Data;
@ -103,17 +113,22 @@ class Archive : public Binary {
Expected<StringRef> getName() const;
Expected<std::string> getFullName() const;
Expected<StringRef> getRawName() const { return Header.getRawName(); }
Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const {
return Header.getLastModified();
}
StringRef getRawLastModified() const {
return Header.getRawLastModified();
}
Expected<unsigned> getUID() const { return Header.getUID(); }
Expected<unsigned> getGID() const { return Header.getGID(); }
Expected<sys::fs::perms> getAccessMode() const {
return Header.getAccessMode();
}
/// \return the size of the archive member without the header or padding.
Expected<uint64_t> getSize() const;
/// \return the size in the archive header for this member.
@ -130,11 +145,12 @@ class Archive : public Binary {
class child_iterator {
Child C;
Error *E;
Error *E = nullptr;
public:
child_iterator() : C(Child(nullptr, nullptr, nullptr)), E(nullptr) {}
child_iterator() : C(Child(nullptr, nullptr, nullptr)) {}
child_iterator(const Child &C, Error *E) : C(C), E(E) {}
const Child *operator->() const { return &C; }
const Child &operator*() const { return C; }
@ -171,14 +187,15 @@ class Archive : public Binary {
uint32_t StringIndex; // Extra index to the string.
public:
bool operator ==(const Symbol &other) const {
return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
}
Symbol(const Archive *p, uint32_t symi, uint32_t stri)
: Parent(p)
, SymbolIndex(symi)
, StringIndex(stri) {}
bool operator ==(const Symbol &other) const {
return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
}
StringRef getName() const;
Expected<Child> getMember() const;
Symbol getNext() const;
@ -186,8 +203,10 @@ class Archive : public Binary {
class symbol_iterator {
Symbol symbol;
public:
symbol_iterator(const Symbol &s) : symbol(s) {}
const Symbol *operator->() const { return &symbol; }
const Symbol &operator*() const { return symbol; }
@ -264,7 +283,7 @@ class Archive : public Binary {
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};
}
}
} // end namespace object
} // end namespace llvm
#endif
#endif // LLVM_OBJECT_ARCHIVE_H

View File

@ -15,10 +15,11 @@
#define LLVM_OBJECT_BINARY_H
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <memory>
#include <utility>
namespace llvm {
@ -29,9 +30,6 @@ namespace object {
class Binary {
private:
Binary() = delete;
Binary(const Binary &other) = delete;
unsigned int TypeID;
protected:
@ -80,6 +78,8 @@ class Binary {
}
public:
Binary() = delete;
Binary(const Binary &other) = delete;
virtual ~Binary();
StringRef getData() const;
@ -173,7 +173,7 @@ OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
std::unique_ptr<MemoryBuffer> Buf)
: Bin(std::move(Bin)), Buf(std::move(Buf)) {}
template <typename T> OwningBinary<T>::OwningBinary() {}
template <typename T> OwningBinary<T>::OwningBinary() = default;
template <typename T>
OwningBinary<T>::OwningBinary(OwningBinary &&Other)
@ -201,7 +201,9 @@ template <typename T> const T* OwningBinary<T>::getBinary() const {
}
Expected<OwningBinary<Binary>> createBinary(StringRef Path);
}
}
#endif
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_BINARY_H

View File

@ -14,28 +14,39 @@
#ifndef LLVM_OBJECT_COFF_H
#define LLVM_OBJECT_COFF_H
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <system_error>
namespace llvm {
template <typename T> class ArrayRef;
namespace object {
class ImportDirectoryEntryRef;
class BaseRelocRef;
class DelayImportDirectoryEntryRef;
class ExportDirectoryEntryRef;
class ImportDirectoryEntryRef;
class ImportedSymbolRef;
class BaseRelocRef;
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
typedef content_iterator<DelayImportDirectoryEntryRef>
delay_import_directory_iterator;
typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator;
typedef content_iterator<BaseRelocRef> base_reloc_iterator;
using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
using delay_import_directory_iterator =
content_iterator<DelayImportDirectoryEntryRef>;
using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>;
using imported_symbol_iterator = content_iterator<ImportedSymbolRef>;
using base_reloc_iterator = content_iterator<BaseRelocRef>;
/// The DOS compatible header at the front of all PE/COFF executables.
struct dos_header {
@ -190,10 +201,10 @@ struct import_lookup_table_entry {
}
};
typedef import_lookup_table_entry<support::little32_t>
import_lookup_table_entry32;
typedef import_lookup_table_entry<support::little64_t>
import_lookup_table_entry64;
using import_lookup_table_entry32 =
import_lookup_table_entry<support::little32_t>;
using import_lookup_table_entry64 =
import_lookup_table_entry<support::little64_t>;
struct delay_import_directory_table_entry {
// dumpbin reports this field as "Characteristics" instead of "Attributes".
@ -226,8 +237,8 @@ union export_address_table_entry {
support::ulittle32_t ForwarderRVA;
};
typedef support::ulittle32_t export_name_pointer_table_entry;
typedef support::ulittle16_t export_ordinal_table_entry;
using export_name_pointer_table_entry = support::ulittle32_t;
using export_ordinal_table_entry = support::ulittle16_t;
struct StringTableOffset {
support::ulittle32_t Zeroes;
@ -250,8 +261,8 @@ struct coff_symbol {
uint8_t NumberOfAuxSymbols;
};
typedef coff_symbol<support::ulittle16_t> coff_symbol16;
typedef coff_symbol<support::ulittle32_t> coff_symbol32;
using coff_symbol16 = coff_symbol<support::ulittle16_t>;
using coff_symbol32 = coff_symbol<support::ulittle32_t>;
// Contains only common parts of coff_symbol16 and coff_symbol32.
struct coff_symbol_generic {
@ -264,9 +275,9 @@ struct coff_symbol_generic {
class COFFSymbolRef {
public:
COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {}
COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {}
COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {}
COFFSymbolRef() = default;
COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {}
COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {}
const void *getRawPtr() const {
return CS16 ? static_cast<const void *>(CS16) : CS32;
@ -396,8 +407,8 @@ class COFFSymbolRef {
private:
bool isSet() const { return CS16 || CS32; }
const coff_symbol16 *CS16;
const coff_symbol32 *CS32;
const coff_symbol16 *CS16 = nullptr;
const coff_symbol32 *CS32 = nullptr;
};
struct coff_section {
@ -418,6 +429,7 @@ struct coff_section {
return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
NumberOfRelocations == UINT16_MAX;
}
uint32_t getAlignment() const {
// The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
// IMAGE_SCN_ALIGN_1BYTES.
@ -508,6 +520,7 @@ struct coff_import_header {
support::ulittle32_t SizeOfData;
support::ulittle16_t OrdinalHint;
support::ulittle16_t TypeInfo;
int getType() const { return TypeInfo & 0x3; }
int getNameType() const { return (TypeInfo >> 2) & 0x7; }
};
@ -518,6 +531,7 @@ struct coff_import_directory_table_entry {
support::ulittle32_t ForwarderChain;
support::ulittle32_t NameRVA;
support::ulittle32_t ImportAddressTableRVA;
bool isNull() const {
return ImportLookupTableRVA == 0 && TimeDateStamp == 0 &&
ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0;
@ -532,6 +546,7 @@ struct coff_tls_directory {
IntTy AddressOfCallBacks;
support::ulittle32_t SizeOfZeroFill;
support::ulittle32_t Characteristics;
uint32_t getAlignment() const {
// Bit [20:24] contains section alignment.
uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
@ -541,8 +556,8 @@ struct coff_tls_directory {
}
};
typedef coff_tls_directory<support::little32_t> coff_tls_directory32;
typedef coff_tls_directory<support::little64_t> coff_tls_directory64;
using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
using coff_tls_directory64 = coff_tls_directory<support::little64_t>;
struct coff_load_configuration32 {
support::ulittle32_t Characteristics;
@ -603,6 +618,7 @@ struct coff_base_reloc_block_header {
struct coff_base_reloc_block_entry {
support::ulittle16_t Data;
int getType() const { return Data >> 12; }
int getOffset() const { return Data & ((1 << 12) - 1); }
};
@ -652,6 +668,7 @@ class COFFObjectFile : public ObjectFile {
return reinterpret_cast<uintptr_t>(SymbolTable32);
return uintptr_t(0);
}
uint16_t getMachine() const {
if (COFFHeader)
return COFFHeader->Machine;
@ -659,6 +676,7 @@ class COFFObjectFile : public ObjectFile {
return COFFBigObjHeader->Machine;
llvm_unreachable("no COFF header!");
}
uint16_t getSizeOfOptionalHeader() const {
if (COFFHeader)
return COFFHeader->isImportLibrary() ? 0
@ -668,6 +686,7 @@ class COFFObjectFile : public ObjectFile {
return 0;
llvm_unreachable("no COFF header!");
}
uint16_t getCharacteristics() const {
if (COFFHeader)
return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
@ -677,6 +696,7 @@ class COFFObjectFile : public ObjectFile {
return 0;
llvm_unreachable("no COFF header!");
}
uint32_t getTimeDateStamp() const {
if (COFFHeader)
return COFFHeader->TimeDateStamp;
@ -684,6 +704,7 @@ class COFFObjectFile : public ObjectFile {
return COFFBigObjHeader->TimeDateStamp;
llvm_unreachable("no COFF header!");
}
uint32_t getNumberOfSections() const {
if (COFFHeader)
return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
@ -691,6 +712,7 @@ class COFFObjectFile : public ObjectFile {
return COFFBigObjHeader->NumberOfSections;
llvm_unreachable("no COFF header!");
}
uint32_t getPointerToSymbolTable() const {
if (COFFHeader)
return COFFHeader->isImportLibrary() ? 0
@ -699,6 +721,7 @@ class COFFObjectFile : public ObjectFile {
return COFFBigObjHeader->PointerToSymbolTable;
llvm_unreachable("no COFF header!");
}
uint32_t getRawNumberOfSymbols() const {
if (COFFHeader)
return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
@ -706,11 +729,13 @@ class COFFObjectFile : public ObjectFile {
return COFFBigObjHeader->NumberOfSymbols;
llvm_unreachable("no COFF header!");
}
uint32_t getNumberOfSymbols() const {
if (!SymbolTable16 && !SymbolTable32)
return 0;
return getRawNumberOfSymbols();
}
protected:
void moveSymbolNext(DataRefImpl &Symb) const override;
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
@ -746,6 +771,7 @@ class COFFObjectFile : public ObjectFile {
public:
COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
section_iterator section_begin() const override;
@ -797,6 +823,7 @@ class COFFObjectFile : public ObjectFile {
std::error_code getDataDirectory(uint32_t index,
const data_directory *&Res) const;
std::error_code getSection(int32_t index, const coff_section *&Res) const;
template <typename coff_symbol_type>
std::error_code getSymbol(uint32_t Index,
const coff_symbol_type *&Res) const {
@ -821,6 +848,7 @@ class COFFObjectFile : public ObjectFile {
}
return object_error::parse_failed;
}
template <typename T>
std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
ErrorOr<COFFSymbolRef> s = getSymbol(index);
@ -829,6 +857,7 @@ class COFFObjectFile : public ObjectFile {
Res = reinterpret_cast<const T *>(s->getRawPtr());
return std::error_code();
}
std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
std::error_code getSymbolName(const coff_symbol_generic *Symbol,
StringRef &Res) const;
@ -885,7 +914,7 @@ class COFFObjectFile : public ObjectFile {
// The iterator for the import directory table.
class ImportDirectoryEntryRef {
public:
ImportDirectoryEntryRef() : OwningObject(nullptr) {}
ImportDirectoryEntryRef() = default;
ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
uint32_t I, const COFFObjectFile *Owner)
: ImportTable(Table), Index(I), OwningObject(Owner) {}
@ -911,12 +940,12 @@ class ImportDirectoryEntryRef {
private:
const coff_import_directory_table_entry *ImportTable;
uint32_t Index;
const COFFObjectFile *OwningObject;
const COFFObjectFile *OwningObject = nullptr;
};
class DelayImportDirectoryEntryRef {
public:
DelayImportDirectoryEntryRef() : OwningObject(nullptr) {}
DelayImportDirectoryEntryRef() = default;
DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
uint32_t I, const COFFObjectFile *Owner)
: Table(T), Index(I), OwningObject(Owner) {}
@ -936,13 +965,13 @@ class DelayImportDirectoryEntryRef {
private:
const delay_import_directory_table_entry *Table;
uint32_t Index;
const COFFObjectFile *OwningObject;
const COFFObjectFile *OwningObject = nullptr;
};
// The iterator for the export directory table entry.
class ExportDirectoryEntryRef {
public:
ExportDirectoryEntryRef() : OwningObject(nullptr) {}
ExportDirectoryEntryRef() = default;
ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
const COFFObjectFile *Owner)
: ExportTable(Table), Index(I), OwningObject(Owner) {}
@ -962,12 +991,12 @@ class ExportDirectoryEntryRef {
private:
const export_directory_table_entry *ExportTable;
uint32_t Index;
const COFFObjectFile *OwningObject;
const COFFObjectFile *OwningObject = nullptr;
};
class ImportedSymbolRef {
public:
ImportedSymbolRef() : OwningObject(nullptr) {}
ImportedSymbolRef() = default;
ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
const COFFObjectFile *Owner)
: Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
@ -987,12 +1016,12 @@ class ImportedSymbolRef {
const import_lookup_table_entry32 *Entry32;
const import_lookup_table_entry64 *Entry64;
uint32_t Index;
const COFFObjectFile *OwningObject;
const COFFObjectFile *OwningObject = nullptr;
};
class BaseRelocRef {
public:
BaseRelocRef() : OwningObject(nullptr) {}
BaseRelocRef() = default;
BaseRelocRef(const coff_base_reloc_block_header *Header,
const COFFObjectFile *Owner)
: Header(Header), Index(0), OwningObject(Owner) {}
@ -1006,7 +1035,7 @@ class BaseRelocRef {
private:
const coff_base_reloc_block_header *Header;
uint32_t Index;
const COFFObjectFile *OwningObject;
const COFFObjectFile *OwningObject = nullptr;
};
// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
@ -1034,6 +1063,7 @@ struct FpoData {
};
} // end namespace object
} // end namespace llvm
#endif
#endif // LLVM_OBJECT_COFF_H

View File

@ -41,9 +41,9 @@ typedef support::ulittle32_t Word;
/// A reference to a string in the string table.
struct Str {
Word Offset;
Word Offset, Size;
StringRef get(StringRef Strtab) const {
return Strtab.data() + Offset;
return {Strtab.data() + Offset, Size};
}
};
@ -59,6 +59,9 @@ template <typename T> struct Range {
/// table.
struct Module {
Word Begin, End;
/// The index of the first Uncommon for this Module.
Word UncBegin;
};
/// This is equivalent to an IR comdat.
@ -82,7 +85,8 @@ struct Symbol {
Word Flags;
enum FlagBits {
FB_visibility, // 2 bits
FB_undefined = FB_visibility + 2,
FB_has_uncommon = FB_visibility + 2,
FB_undefined,
FB_weak,
FB_common,
FB_indirect,
@ -94,10 +98,6 @@ struct Symbol {
FB_unnamed_addr,
FB_executable,
};
/// The index into the Uncommon table, or -1 if this symbol does not have an
/// Uncommon.
Word UncommonIndex;
};
/// This data structure contains rarely used symbol fields and is optionally
@ -249,15 +249,9 @@ class Reader {
/// Reader::module_symbols().
class Reader::SymbolRef : public Symbol {
const storage::Symbol *SymI, *SymE;
const storage::Uncommon *UncI;
const Reader *R;
public:
SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE,
const Reader *R)
: SymI(SymI), SymE(SymE), R(R) {
read();
}
void read() {
if (SymI == SymE)
return;
@ -267,16 +261,24 @@ class Reader::SymbolRef : public Symbol {
ComdatIndex = SymI->ComdatIndex;
Flags = SymI->Flags;
uint32_t UncI = SymI->UncommonIndex;
if (UncI != -1u) {
const storage::Uncommon &Unc = R->Uncommons[UncI];
CommonSize = Unc.CommonSize;
CommonAlign = Unc.CommonAlign;
COFFWeakExternFallbackName = R->str(Unc.COFFWeakExternFallbackName);
if (Flags & (1 << storage::Symbol::FB_has_uncommon)) {
CommonSize = UncI->CommonSize;
CommonAlign = UncI->CommonAlign;
COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName);
}
}
public:
SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE,
const storage::Uncommon *UncI, const Reader *R)
: SymI(SymI), SymE(SymE), UncI(UncI), R(R) {
read();
}
void moveNext() {
++SymI;
if (Flags & (1 << storage::Symbol::FB_has_uncommon))
++UncI;
read();
}
@ -284,15 +286,16 @@ class Reader::SymbolRef : public Symbol {
};
inline Reader::symbol_range Reader::symbols() const {
return {SymbolRef(Symbols.begin(), Symbols.end(), this),
SymbolRef(Symbols.end(), Symbols.end(), this)};
return {SymbolRef(Symbols.begin(), Symbols.end(), Uncommons.begin(), this),
SymbolRef(Symbols.end(), Symbols.end(), nullptr, this)};
}
inline Reader::symbol_range Reader::module_symbols(unsigned I) const {
const storage::Module &M = Modules[I];
const storage::Symbol *MBegin = Symbols.begin() + M.Begin,
*MEnd = Symbols.begin() + M.End;
return {SymbolRef(MBegin, MEnd, this), SymbolRef(MEnd, MEnd, this)};
return {SymbolRef(MBegin, MEnd, Uncommons.begin() + M.UncBegin, this),
SymbolRef(MEnd, MEnd, nullptr, this)};
}
}

View File

@ -14,39 +14,46 @@
#ifndef LLVM_OBJECT_OBJECTFILE_H
#define LLVM_OBJECT_OBJECTFILE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstring>
#include <cassert>
#include <cstdint>
#include <memory>
#include <system_error>
namespace llvm {
class ARMAttributeParser;
namespace object {
class ObjectFile;
class COFFObjectFile;
class MachOObjectFile;
class WasmObjectFile;
class ObjectFile;
class SectionRef;
class SymbolRef;
class symbol_iterator;
class SectionRef;
typedef content_iterator<SectionRef> section_iterator;
class WasmObjectFile;
using section_iterator = content_iterator<SectionRef>;
/// This is a value type class that represents a single relocation in the list
/// of relocations in the object file.
class RelocationRef {
DataRefImpl RelocationPimpl;
const ObjectFile *OwningObject;
const ObjectFile *OwningObject = nullptr;
public:
RelocationRef() : OwningObject(nullptr) { }
RelocationRef() = default;
RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
bool operator==(const RelocationRef &Other) const;
@ -65,18 +72,19 @@ class RelocationRef {
DataRefImpl getRawDataRefImpl() const;
const ObjectFile *getObject() const;
};
typedef content_iterator<RelocationRef> relocation_iterator;
using relocation_iterator = content_iterator<RelocationRef>;
/// This is a value type class that represents a single section in the list of
/// sections in the object file.
class SectionRef {
friend class SymbolRef;
DataRefImpl SectionPimpl;
const ObjectFile *OwningObject;
const ObjectFile *OwningObject = nullptr;
public:
SectionRef() : OwningObject(nullptr) { }
SectionRef() = default;
SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
bool operator==(const SectionRef &Other) const;
@ -119,8 +127,6 @@ class SymbolRef : public BasicSymbolRef {
friend class SectionRef;
public:
SymbolRef() : BasicSymbolRef() {}
enum Type {
ST_Unknown, // Type not specified
ST_Data,
@ -130,6 +136,7 @@ class SymbolRef : public BasicSymbolRef {
ST_Other
};
SymbolRef() = default;
SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
@ -179,8 +186,6 @@ class symbol_iterator : public basic_symbol_iterator {
/// to create.
class ObjectFile : public SymbolicFile {
virtual void anchor();
ObjectFile() = delete;
ObjectFile(const ObjectFile &other) = delete;
protected:
ObjectFile(unsigned int Type, MemoryBufferRef Source);
@ -198,6 +203,7 @@ class ObjectFile : public SymbolicFile {
// Implementations assume that the DataRefImpl is valid and has not been
// modified externally. It's UB otherwise.
friend class SymbolRef;
virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
std::error_code printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
@ -211,6 +217,7 @@ class ObjectFile : public SymbolicFile {
// Same as above for SectionRef.
friend class SectionRef;
virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
virtual std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const = 0;
@ -242,12 +249,15 @@ class ObjectFile : public SymbolicFile {
uint64_t getSymbolValue(DataRefImpl Symb) const;
public:
ObjectFile() = delete;
ObjectFile(const ObjectFile &other) = delete;
uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
assert(getSymbolFlags(Symb) & SymbolRef::SF_Common);
return getCommonSymbolSizeImpl(Symb);
}
typedef iterator_range<symbol_iterator> symbol_iterator_range;
using symbol_iterator_range = iterator_range<symbol_iterator>;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());
}
@ -255,7 +265,7 @@ class ObjectFile : public SymbolicFile {
virtual section_iterator section_begin() const = 0;
virtual section_iterator section_end() const = 0;
typedef iterator_range<section_iterator> section_iterator_range;
using section_iterator_range = iterator_range<section_iterator>;
section_iterator_range sections() const {
return section_iterator_range(section_begin(), section_end());
}
@ -297,7 +307,6 @@ class ObjectFile : public SymbolicFile {
return createObjectFile(Object, sys::fs::file_magic::unknown);
}
static inline bool classof(const Binary *v) {
return v->isObject();
}
@ -354,7 +363,6 @@ inline const ObjectFile *SymbolRef::getObject() const {
return cast<ObjectFile>(O);
}
/// SectionRef
inline SectionRef::SectionRef(DataRefImpl SectionP,
const ObjectFile *Owner)
@ -479,8 +487,8 @@ inline const ObjectFile *RelocationRef::getObject() const {
return OwningObject;
}
} // end namespace object
} // end namespace llvm
#endif
#endif // LLVM_OBJECT_OBJECTFILE_H

View File

@ -14,10 +14,19 @@
#ifndef LLVM_OBJECT_SYMBOLICFILE_H
#define LLVM_OBJECT_SYMBOLICFILE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cinttypes>
#include <utility>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <memory>
#include <system_error>
namespace llvm {
namespace object {
@ -29,6 +38,7 @@ union DataRefImpl {
uint32_t a, b;
} d;
uintptr_t p;
DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); }
};
@ -87,7 +97,7 @@ class SymbolicFile;
/// symbols in the object file.
class BasicSymbolRef {
DataRefImpl SymbolPimpl;
const SymbolicFile *OwningObject;
const SymbolicFile *OwningObject = nullptr;
public:
enum Flags : unsigned {
@ -108,7 +118,7 @@ class BasicSymbolRef {
// (IR only)
};
BasicSymbolRef() : OwningObject(nullptr) { }
BasicSymbolRef() = default;
BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner);
bool operator==(const BasicSymbolRef &Other) const;
@ -125,12 +135,12 @@ class BasicSymbolRef {
const SymbolicFile *getObject() const;
};
typedef content_iterator<BasicSymbolRef> basic_symbol_iterator;
using basic_symbol_iterator = content_iterator<BasicSymbolRef>;
class SymbolicFile : public Binary {
public:
~SymbolicFile() override;
SymbolicFile(unsigned int Type, MemoryBufferRef Source);
~SymbolicFile() override;
// virtual interface.
virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
@ -145,7 +155,7 @@ class SymbolicFile : public Binary {
virtual basic_symbol_iterator symbol_end() const = 0;
// convenience wrappers.
typedef iterator_range<basic_symbol_iterator> basic_symbol_iterator_range;
using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>;
basic_symbol_iterator_range symbols() const {
return basic_symbol_iterator_range(symbol_begin(), symbol_end());
}
@ -199,7 +209,7 @@ inline const SymbolicFile *BasicSymbolRef::getObject() const {
return OwningObject;
}
}
}
} // end namespace object
} // end namespace llvm
#endif
#endif // LLVM_OBJECT_SYMBOLICFILE_H

View File

@ -236,7 +236,7 @@ template <> struct MappingTraits<DWARFYAML::InitialLength> {
static void mapping(IO &IO, DWARFYAML::InitialLength &DWARF);
};
#define HANDLE_DW_TAG(unused, name) \
#define HANDLE_DW_TAG(unused, name, unused2, unused3) \
io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name);
template <> struct ScalarEnumerationTraits<dwarf::Tag> {
@ -266,7 +266,7 @@ template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> {
}
};
#define HANDLE_DW_AT(unused, name) \
#define HANDLE_DW_AT(unused, name, unused2, unused3) \
io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name);
template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
@ -276,7 +276,7 @@ template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
}
};
#define HANDLE_DW_FORM(unused, name) \
#define HANDLE_DW_FORM(unused, name, unused2, unused3) \
io.enumCase(value, "DW_FORM_" #name, dwarf::DW_FORM_##name);
template <> struct ScalarEnumerationTraits<dwarf::Form> {

View File

@ -93,11 +93,7 @@ template <typename PassName> Pass *callTargetMachineCtor(TargetMachine *TM) {
/// static RegisterPass<YourPassClassName> tmp("passopt", "My Pass Name");
///
/// This statement will cause your pass to be created by calling the default
/// constructor exposed by the pass. If you have a different constructor that
/// must be called, create a global constructor function (which takes the
/// arguments you need and returns a Pass*) and register your pass like this:
///
/// static RegisterPass<PassClassName> tmp("passopt", "My Name");
/// constructor exposed by the pass.
///
template <typename passName> struct RegisterPass : public PassInfo {
// Register Pass using default constructor...

View File

@ -78,33 +78,33 @@ ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7,
FK_NEON, ARM::AEK_DSP)
ARM_ARCH("armv7ve", AK_ARMV7VE, "7VE", "v7ve", ARMBuildAttrs::CPUArch::v7,
FK_NEON, (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
ARM::AEK_HWDIVARM | ARM::AEK_HWDIV | ARM::AEK_DSP))
ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7,
FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
FK_NONE, (ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7,
FK_NONE, ARM::AEK_HWDIV)
FK_NONE, ARM::AEK_HWDIVTHUMB)
ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M,
FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
FK_NONE, (ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
FK_CRYPTO_NEON_FP_ARMV8,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC))
ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC))
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC))
ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a",
ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
ARM_ARCH("armv8-r", AK_ARMV8R, "8-R", "v8r", ARMBuildAttrs::CPUArch::v8_R,
FK_NEON_FP_ARMV8,
(ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIV |
(ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
ARM::AEK_DSP | ARM::AEK_CRC))
ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base",
ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIV)
ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIVTHUMB)
ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main",
ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIV)
ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIVTHUMB)
// Non-standard Arch names.
ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE,
FK_NONE, ARM::AEK_NONE)
@ -128,7 +128,7 @@ ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc")
ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto")
ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp")
ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr)
ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV), nullptr, nullptr)
ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB), nullptr, nullptr)
ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr)
ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr)
ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, nullptr, nullptr)
@ -147,9 +147,9 @@ ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
#endif
ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID)
ARM_HW_DIV_NAME("none", ARM::AEK_NONE)
ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIV)
ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIVTHUMB)
ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM)
ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
#undef ARM_HW_DIV_NAME
#ifndef ARM_CPU_NAME
@ -205,20 +205,20 @@ ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP))
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_HWDIV))
ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, 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 |
ARM::AEK_HWDIV))
ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("cortex-a15", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV))
ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("cortex-a17", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV))
ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("krait", AK_ARMV7A, FK_NEON_VFPV4, false,
(ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
(ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-r5", AK_ARMV7R, FK_VFPV3_D16, false,
@ -249,7 +249,7 @@ ARM_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("swift", AK_ARMV7S, FK_NEON_VFPV4, true,
(ARM::AEK_HWDIVARM | ARM::AEK_HWDIV))
(ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
// Invalid CPU
ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, ARM::AEK_INVALID)
#undef ARM_CPU_NAME

View File

@ -47,7 +47,9 @@ template <class T, size_t Align = alignof(T)> class ArrayRecycler {
FreeList *Entry = Bucket[Idx];
if (!Entry)
return nullptr;
__asan_unpoison_memory_region(Entry, Capacity::get(Idx).getSize());
Bucket[Idx] = Entry->Next;
__msan_allocated_memory(Entry, Capacity::get(Idx).getSize());
return reinterpret_cast<T*>(Entry);
}
@ -59,6 +61,7 @@ template <class T, size_t Align = alignof(T)> class ArrayRecycler {
Bucket.resize(size_t(Idx) + 1);
Entry->Next = Bucket[Idx];
Bucket[Idx] = Entry;
__asan_poison_memory_region(Ptr, Capacity::get(Idx).getSize());
}
public:

View File

@ -162,6 +162,11 @@ class VarStreamArrayIterator
return ThisValue;
}
ValueType &operator*() {
assert(Array && !HasError);
return ThisValue;
}
IterType &operator+=(unsigned N) {
for (unsigned I = 0; I < N; ++I) {
// We are done with the current record, discard it so that we are

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,15 @@ enum LLVMConstants : uint32_t {
DWARF_VERSION = 4, // Default dwarf version we output.
DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes.
DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames.
DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges.
DW_ARANGES_VERSION = 2, // Section version number for .debug_aranges.
// Identifiers we use to distinguish vendor extensions.
DWARF_VENDOR_DWARF = 0, // Defined in v2 or later of the DWARF standard.
DWARF_VENDOR_APPLE = 1,
DWARF_VENDOR_BORLAND = 2,
DWARF_VENDOR_GNU = 3,
DWARF_VENDOR_GOOGLE = 4,
DWARF_VENDOR_LLVM = 5,
DWARF_VENDOR_MIPS = 6
};
// Special ID values that distinguish a CIE from a FDE in DWARF CFI.
@ -55,7 +63,7 @@ const uint32_t DW_CIE_ID = UINT32_MAX;
const uint64_t DW64_CIE_ID = UINT64_MAX;
enum Tag : uint16_t {
#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID,
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) DW_TAG_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_TAG_lo_user = 0x4080,
DW_TAG_hi_user = 0xffff,
@ -92,20 +100,20 @@ inline bool isType(Tag T) {
/// Attributes.
enum Attribute : uint16_t {
#define HANDLE_DW_AT(ID, NAME) DW_AT_##NAME = ID,
#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) DW_AT_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_AT_lo_user = 0x2000,
DW_AT_hi_user = 0x3fff,
};
enum Form : uint16_t {
#define HANDLE_DW_FORM(ID, NAME) DW_FORM_##NAME = ID,
#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) DW_FORM_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_FORM_lo_user = 0x1f00, ///< Not specified by DWARF.
};
enum LocationAtom {
#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID,
#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) DW_OP_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff,
@ -113,7 +121,7 @@ enum LocationAtom {
};
enum TypeKind {
#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID,
#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) DW_ATE_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_ATE_lo_user = 0x80,
DW_ATE_hi_user = 0xff
@ -164,7 +172,7 @@ enum DefaultedMemberAttribute {
};
enum SourceLanguage {
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID,
#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) DW_LANG_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_LANG_lo_user = 0x8000,
DW_LANG_hi_user = 0xffff
@ -220,8 +228,8 @@ enum LineNumberExtendedOps {
DW_LNE_hi_user = 0xff
};
enum LinerNumberEntryFormat {
#define HANDLE_DW_LNCT(ID, NAME) DW_DEFAULTED_##NAME = ID,
enum LineNumberEntryFormat {
#define HANDLE_DW_LNCT(ID, NAME) DW_LNCT_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_LNCT_lo_user = 0x2000,
DW_LNCT_hi_user = 0x3fff,
@ -406,6 +414,40 @@ unsigned getAttributeEncoding(StringRef EncodingString);
unsigned getMacinfo(StringRef MacinfoString);
/// @}
/// \defgroup DwarfConstantsVersioning Dwarf version for constants
///
/// For constants defined by DWARF, returns the DWARF version when the constant
/// was first defined. For vendor extensions, if there is a version-related
/// policy for when to emit it, returns a version number for that policy.
/// Otherwise returns 0.
///
/// @{
unsigned TagVersion(Tag T);
unsigned AttributeVersion(Attribute A);
unsigned FormVersion(Form F);
unsigned OperationVersion(LocationAtom O);
unsigned AttributeEncodingVersion(TypeKind E);
unsigned LanguageVersion(SourceLanguage L);
/// @}
/// \defgroup DwarfConstantsVendor Dwarf "vendor" for constants
///
/// These functions return an identifier describing "who" defined the constant,
/// either the DWARF standard itself or the vendor who defined the extension.
///
/// @{
unsigned TagVendor(Tag T);
unsigned AttributeVendor(Attribute A);
unsigned FormVendor(Form F);
unsigned OperationVendor(LocationAtom O);
unsigned AttributeEncodingVendor(TypeKind E);
unsigned LanguageVendor(SourceLanguage L);
/// @}
/// Tells whether the specified form is defined in the specified version,
/// or is an extension if extensions are allowed.
bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true);
/// \brief Returns the symbolic string representing Val when used as a value
/// for attribute Attr.
StringRef AttributeValueString(uint16_t Attr, unsigned Val);

View File

@ -276,32 +276,25 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
template <class N, class GraphT>
void Split(DominatorTreeBaseByGraphTraits<GraphT> &DT,
typename GraphT::NodeRef NewBB) {
template <class N>
void Split(typename GraphTraits<N>::NodeRef NewBB) {
using GraphT = GraphTraits<N>;
using NodeRef = typename GraphT::NodeRef;
assert(std::distance(GraphT::child_begin(NewBB),
GraphT::child_end(NewBB)) == 1 &&
"NewBB should have a single successor!");
typename GraphT::NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
std::vector<typename GraphT::NodeRef> PredBlocks;
typedef GraphTraits<Inverse<N>> InvTraits;
for (typename InvTraits::ChildIteratorType
PI = InvTraits::child_begin(NewBB),
PE = InvTraits::child_end(NewBB);
PI != PE; ++PI)
PredBlocks.push_back(*PI);
std::vector<NodeRef> PredBlocks;
for (const auto Pred : children<Inverse<N>>(NewBB))
PredBlocks.push_back(Pred);
assert(!PredBlocks.empty() && "No predblocks?");
bool NewBBDominatesNewBBSucc = true;
for (typename InvTraits::ChildIteratorType
PI = InvTraits::child_begin(NewBBSucc),
E = InvTraits::child_end(NewBBSucc);
PI != E; ++PI) {
typename InvTraits::NodeRef ND = *PI;
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
DT.isReachableFromEntry(ND)) {
for (const auto Pred : children<Inverse<N>>(NewBBSucc)) {
if (Pred != NewBB && !dominates(NewBBSucc, Pred) &&
isReachableFromEntry(Pred)) {
NewBBDominatesNewBBSucc = false;
break;
}
@ -312,7 +305,7 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
NodeT *NewBBIDom = nullptr;
unsigned i = 0;
for (i = 0; i < PredBlocks.size(); ++i)
if (DT.isReachableFromEntry(PredBlocks[i])) {
if (isReachableFromEntry(PredBlocks[i])) {
NewBBIDom = PredBlocks[i];
break;
}
@ -324,18 +317,18 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
return;
for (i = i + 1; i < PredBlocks.size(); ++i) {
if (DT.isReachableFromEntry(PredBlocks[i]))
NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
if (isReachableFromEntry(PredBlocks[i]))
NewBBIDom = findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
}
// Create the new dominator tree node... and set the idom of NewBB.
DomTreeNodeBase<NodeT> *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom);
DomTreeNodeBase<NodeT> *NewBBNode = addNewBlock(NewBB, NewBBIDom);
// If NewBB strictly dominates other blocks, then it is now the immediate
// dominator of NewBBSucc. Update the dominator tree as appropriate.
if (NewBBDominatesNewBBSucc) {
DomTreeNodeBase<NodeT> *NewBBSuccNode = DT.getNode(NewBBSucc);
DT.changeImmediateDominator(NewBBSuccNode, NewBBNode);
DomTreeNodeBase<NodeT> *NewBBSuccNode = getNode(NewBBSucc);
changeImmediateDominator(NewBBSuccNode, NewBBNode);
}
}
@ -379,7 +372,7 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
return true;
for (const auto &DomTreeNode : this->DomTreeNodes) {
for (const auto &DomTreeNode : DomTreeNodes) {
NodeT *BB = DomTreeNode.first;
typename DomTreeNodeMapType::const_iterator OI =
OtherDomTreeNodes.find(BB);
@ -663,10 +656,9 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
/// tree to reflect this change.
void splitBlock(NodeT *NewBB) {
if (this->IsPostDominators)
this->Split<Inverse<NodeT *>, GraphTraits<Inverse<NodeT *>>>(*this,
NewBB);
Split<Inverse<NodeT *>>(NewBB);
else
this->Split<NodeT *, GraphTraits<NodeT *>>(*this, NewBB);
Split<NodeT *>(NewBB);
}
/// print - Convert to human readable form
@ -677,7 +669,7 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
o << "Inorder PostDominator Tree: ";
else
o << "Inorder Dominator Tree: ";
if (!this->DFSInfoValid)
if (!DFSInfoValid)
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
o << "\n";
@ -712,12 +704,12 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
// immediate dominator.
NodeT *IDom = getIDom(BB);
assert(IDom || this->DomTreeNodes[nullptr]);
assert(IDom || DomTreeNodes[nullptr]);
DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
// Add a new tree node for this NodeT, and link it as a child of
// IDomNode
return (this->DomTreeNodes[BB] = IDomNode->addChild(
return (DomTreeNodes[BB] = IDomNode->addChild(
llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
}
@ -780,7 +772,7 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
template <class FT> void recalculate(FT &F) {
typedef GraphTraits<FT *> TraitsTy;
reset();
this->Vertex.push_back(nullptr);
Vertex.push_back(nullptr);
if (!this->IsPostDominators) {
// Initialize root

View File

@ -143,10 +143,9 @@ class GraphWriter {
void writeNodes() {
// Loop over the graph, printing it out...
for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G);
I != E; ++I)
if (!isNodeHidden(*I))
writeNode(*I);
for (const auto Node : nodes<GraphType>(G))
if (!isNodeHidden(Node))
writeNode(Node);
}
bool isNodeHidden(NodeRef Node) {

View File

@ -39,100 +39,123 @@ class raw_ostream;
class LLT {
public:
enum TypeKind : uint16_t {
Invalid,
Scalar,
Pointer,
Vector,
};
/// Get a low-level scalar or aggregate "bag of bits".
static LLT scalar(unsigned SizeInBits) {
assert(SizeInBits > 0 && "invalid scalar size");
return LLT{Scalar, 1, SizeInBits};
return LLT{/*isPointer=*/false, /*isVector=*/false, /*NumElements=*/0,
SizeInBits, /*AddressSpace=*/0};
}
/// Get a low-level pointer in the given address space (defaulting to 0).
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
return LLT{Pointer, AddressSpace, SizeInBits};
assert(SizeInBits > 0 && "invalid pointer size");
return LLT{/*isPointer=*/true, /*isVector=*/false, /*NumElements=*/0,
SizeInBits, AddressSpace};
}
/// Get a low-level vector of some number of elements and element width.
/// \p NumElements must be at least 2.
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
assert(NumElements > 1 && "invalid number of vector elements");
return LLT{Vector, NumElements, ScalarSizeInBits};
assert(ScalarSizeInBits > 0 && "invalid vector element size");
return LLT{/*isPointer=*/false, /*isVector=*/true, NumElements,
ScalarSizeInBits, /*AddressSpace=*/0};
}
/// Get a low-level vector of some number of elements and element type.
static LLT vector(uint16_t NumElements, LLT ScalarTy) {
assert(NumElements > 1 && "invalid number of vector elements");
assert(ScalarTy.isScalar() && "invalid vector element type");
return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
assert(!ScalarTy.isVector() && "invalid vector element type");
return LLT{ScalarTy.isPointer(), /*isVector=*/true, NumElements,
ScalarTy.getSizeInBits(),
ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
}
explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
: SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
"invalid number of vector elements");
explicit LLT(bool isPointer, bool isVector, uint16_t NumElements,
unsigned SizeInBits, unsigned AddressSpace) {
init(isPointer, isVector, NumElements, SizeInBits, AddressSpace);
}
explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
explicit LLT() : IsPointer(false), IsVector(false), RawData(0) {}
explicit LLT(MVT VT);
bool isValid() const { return Kind != Invalid; }
bool isValid() const { return RawData != 0; }
bool isScalar() const { return Kind == Scalar; }
bool isScalar() const { return isValid() && !IsPointer && !IsVector; }
bool isPointer() const { return Kind == Pointer; }
bool isPointer() const { return isValid() && IsPointer && !IsVector; }
bool isVector() const { return Kind == Vector; }
bool isVector() const { return isValid() && IsVector; }
/// Returns the number of elements in a vector LLT. Must only be called on
/// vector types.
uint16_t getNumElements() const {
assert(isVector() && "cannot get number of elements on scalar/aggregate");
return ElementsOrAddrSpace;
assert(IsVector && "cannot get number of elements on scalar/aggregate");
if (!IsPointer)
return getFieldValue(VectorElementsFieldInfo);
else
return getFieldValue(PointerVectorElementsFieldInfo);
}
/// Returns the total size of the type. Must only be called on sized types.
unsigned getSizeInBits() const {
if (isPointer() || isScalar())
return SizeInBits;
return SizeInBits * ElementsOrAddrSpace;
return getScalarSizeInBits();
return getScalarSizeInBits() * getNumElements();
}
unsigned getScalarSizeInBits() const {
return SizeInBits;
assert(RawData != 0 && "Invalid Type");
if (!IsVector) {
if (!IsPointer)
return getFieldValue(ScalarSizeFieldInfo);
else
return getFieldValue(PointerSizeFieldInfo);
} else {
if (!IsPointer)
return getFieldValue(VectorSizeFieldInfo);
else
return getFieldValue(PointerVectorSizeFieldInfo);
}
}
unsigned getAddressSpace() const {
assert(isPointer() && "cannot get address space of non-pointer type");
return ElementsOrAddrSpace;
assert(RawData != 0 && "Invalid Type");
assert(IsPointer && "cannot get address space of non-pointer type");
if (!IsVector)
return getFieldValue(PointerAddressSpaceFieldInfo);
else
return getFieldValue(PointerVectorAddressSpaceFieldInfo);
}
/// Returns the vector's element type. Only valid for vector types.
LLT getElementType() const {
assert(isVector() && "cannot get element type of scalar/aggregate");
return scalar(SizeInBits);
if (IsPointer)
return pointer(getAddressSpace(), getScalarSizeInBits());
else
return scalar(getScalarSizeInBits());
}
/// Get a low-level type with half the size of the original, by halving the
/// size of the scalar type involved. For example `s32` will become `s16`,
/// `<2 x s32>` will become `<2 x s16>`.
LLT halfScalarSize() const {
assert(!isPointer() && getScalarSizeInBits() > 1 &&
assert(!IsPointer && getScalarSizeInBits() > 1 &&
getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
return LLT{/*isPointer=*/false, IsVector ? true : false,
IsVector ? getNumElements() : (uint16_t)0,
getScalarSizeInBits() / 2, /*AddressSpace=*/0};
}
/// Get a low-level type with twice the size of the original, by doubling the
/// size of the scalar type involved. For example `s32` will become `s64`,
/// `<2 x s32>` will become `<2 x s64>`.
LLT doubleScalarSize() const {
assert(!isPointer() && "cannot change size of this type");
return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
assert(!IsPointer && "cannot change size of this type");
return LLT{/*isPointer=*/false, IsVector ? true : false,
IsVector ? getNumElements() : (uint16_t)0,
getScalarSizeInBits() * 2, /*AddressSpace=*/0};
}
/// Get a low-level type with half the size of the original, by halving the
@ -140,13 +163,13 @@ class LLT {
/// a vector type with an even number of elements. For example `<4 x s32>`
/// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
LLT halfElements() const {
assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
"cannot half odd vector");
if (ElementsOrAddrSpace == 2)
return scalar(SizeInBits);
assert(isVector() && getNumElements() % 2 == 0 && "cannot half odd vector");
if (getNumElements() == 2)
return scalar(getScalarSizeInBits());
return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
SizeInBits};
return LLT{/*isPointer=*/false, /*isVector=*/true,
(uint16_t)(getNumElements() / 2), getScalarSizeInBits(),
/*AddressSpace=*/0};
}
/// Get a low-level type with twice the size of the original, by doubling the
@ -154,25 +177,105 @@ class LLT {
/// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
/// the number of elements in sN produces <2 x sN>.
LLT doubleElements() const {
assert(!isPointer() && "cannot double elements in pointer");
return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
SizeInBits};
return LLT{IsPointer ? true : false, /*isVector=*/true,
(uint16_t)(getNumElements() * 2), getScalarSizeInBits(),
IsPointer ? getAddressSpace() : 0};
}
void print(raw_ostream &OS) const;
bool operator==(const LLT &RHS) const {
return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
RHS.RawData == RawData;
}
bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
friend struct DenseMapInfo<LLT>;
private:
unsigned SizeInBits;
uint16_t ElementsOrAddrSpace;
TypeKind Kind;
/// LLT is packed into 64 bits as follows:
/// isPointer : 1
/// isVector : 1
/// with 62 bits remaining for Kind-specific data, packed in bitfields
/// as described below. As there isn't a simple portable way to pack bits
/// into bitfields, here the different fields in the packed structure is
/// described in static const *Field variables. Each of these variables
/// is a 2-element array, with the first element describing the bitfield size
/// and the second element describing the bitfield offset.
typedef int BitFieldInfo[2];
///
/// This is how the bitfields are packed per Kind:
/// * Invalid:
/// gets encoded as RawData == 0, as that is an invalid encoding, since for
/// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
/// SizeInBits: 32;
static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0};
/// * Pointer (isPointer == 1 && isVector == 0):
/// SizeInBits: 16;
/// AddressSpace: 23;
static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0};
static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
23, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
/// NumElements: 16;
/// SizeOfElement: 32;
static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 0};
static const constexpr BitFieldInfo VectorSizeFieldInfo{
32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
/// NumElements: 16;
/// SizeOfElement: 16;
/// AddressSpace: 23;
static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0};
static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{
16,
PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]};
static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{
23, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]};
uint64_t IsPointer : 1;
uint64_t IsVector : 1;
uint64_t RawData : 62;
static uint64_t getMask(const BitFieldInfo FieldInfo) {
const int FieldSizeInBits = FieldInfo[0];
return (((uint64_t)1) << FieldSizeInBits) - 1;
}
static uint64_t maskAndShift(uint64_t Val, uint64_t Mask, uint8_t Shift) {
assert(Val <= Mask && "Value too large for field");
return (Val & Mask) << Shift;
}
static uint64_t maskAndShift(uint64_t Val, const BitFieldInfo FieldInfo) {
return maskAndShift(Val, getMask(FieldInfo), FieldInfo[1]);
}
uint64_t getFieldValue(const BitFieldInfo FieldInfo) const {
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
}
void init(bool IsPointer, bool IsVector, uint16_t NumElements,
unsigned SizeInBits, unsigned AddressSpace) {
this->IsPointer = IsPointer;
this->IsVector = IsVector;
if (!IsVector) {
if (!IsPointer)
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
else
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
} else {
assert(NumElements > 1 && "invalid number of vector elements");
if (!IsPointer)
RawData = maskAndShift(NumElements, VectorElementsFieldInfo) |
maskAndShift(SizeInBits, VectorSizeFieldInfo);
else
RawData =
maskAndShift(NumElements, PointerVectorElementsFieldInfo) |
maskAndShift(SizeInBits, PointerVectorSizeFieldInfo) |
maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo);
}
}
};
inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
@ -182,14 +285,18 @@ inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
template<> struct DenseMapInfo<LLT> {
static inline LLT getEmptyKey() {
return LLT{LLT::Invalid, 0, -1u};
LLT Invalid;
Invalid.IsPointer = true;
return Invalid;
}
static inline LLT getTombstoneKey() {
return LLT{LLT::Invalid, 0, -2u};
LLT Invalid;
Invalid.IsVector = true;
return Invalid;
}
static inline unsigned getHashValue(const LLT &Ty) {
uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
uint64_t Val = ((uint64_t)Ty.RawData) << 2 | ((uint64_t)Ty.IsPointer) << 1 |
((uint64_t)Ty.IsVector);
return DenseMapInfo<uint64_t>::getHashValue(Val);
}
static bool isEqual(const LLT &LHS, const LLT &RHS) {

View File

@ -18,6 +18,7 @@
#include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <type_traits>
#include <limits>
@ -198,6 +199,21 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
return countTrailingZeros(Val, ZB_Undefined);
}
/// \brief Create a bitmask with the N right-most bits set to 1, and all other
/// bits set to 0. Only unsigned types are allowed.
template <typename T> T maskTrailingOnes(unsigned N) {
static_assert(std::is_unsigned<T>::value, "Invalid type!");
const unsigned Bits = CHAR_BIT * sizeof(T);
assert(N <= Bits && "Invalid bit index");
return N == 0 ? 0 : (T(-1) >> (Bits - N));
}
/// \brief Create a bitmask with the N left-most bits set to 1, and all other
/// bits set to 0. Only unsigned types are allowed.
template <typename T> T maskLeadingOnes(unsigned N) {
return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
}
/// \brief Get the index of the last set bit starting from the least
/// significant bit.
///

View File

@ -42,13 +42,16 @@ class Recycler {
FreeNode *pop_val() {
auto *Val = FreeList;
__asan_unpoison_memory_region(Val, Size);
FreeList = FreeList->Next;
__msan_allocated_memory(Val, Size);
return Val;
}
void push(FreeNode *N) {
N->Next = FreeList;
FreeList = N;
__asan_poison_memory_region(N, Size);
}
public:

View File

@ -57,7 +57,7 @@ namespace llvm {
/// isValid - returns the error encountered during regex compilation, or
/// matching, if any.
bool isValid(std::string &Error);
bool isValid(std::string &Error) const;
/// getNumMatches - In a valid regex, return the number of parenthesized
/// matches it contains. The number filled in by match will include this

View File

@ -75,7 +75,7 @@ enum ArchExtKind : unsigned {
AEK_CRC = 0x2,
AEK_CRYPTO = 0x4,
AEK_FP = 0x8,
AEK_HWDIV = 0x10,
AEK_HWDIVTHUMB = 0x10,
AEK_HWDIVARM = 0x20,
AEK_MP = 0x40,
AEK_SIMD = 0x80,

View File

@ -27,6 +27,8 @@ class StringToOffsetTable {
std::string AggregateString;
public:
bool Empty() const { return StringOffset.empty(); }
unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
auto IterBool =
StringOffset.insert(std::make_pair(Str, AggregateString.size()));

View File

@ -230,6 +230,12 @@ class TargetLoweringBase {
return MVT::getIntegerVT(DL.getPointerSizeInBits(AS));
}
/// Return the type for frame index, which is determined by
/// the alloca address space specified through the data layout.
MVT getFrameIndexTy(const DataLayout &DL) const {
return getPointerTy(DL, DL.getAllocaAddrSpace());
}
/// EVT is not used in-tree, but is used by out-of-tree target.
/// A documentation for this function would be nice...
virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const;
@ -2807,7 +2813,7 @@ class TargetLowering : public TargetLoweringBase {
/// Return true if the target may be able emit the call instruction as a tail
/// call. This is used by optimization passes to determine if it's profitable
/// to duplicate return instructions to enable tailcall optimization.
virtual bool mayBeEmittedAsTailCall(CallInst *) const {
virtual bool mayBeEmittedAsTailCall(const CallInst *) const {
return false;
}

View File

@ -65,14 +65,6 @@ template <typename T> class ArrayRef;
/// Blocks containing EHPads, allocas, invokes, or vastarts are not valid.
static bool isBlockValidForExtraction(const BasicBlock &BB);
/// \brief Create a code extractor for a single basic block.
///
/// In this formation, we don't require a dominator tree. The given basic
/// block is set up for extraction.
CodeExtractor(BasicBlock *BB, bool AggregateArgs = false,
BlockFrequencyInfo *BFI = nullptr,
BranchProbabilityInfo *BPI = nullptr);
/// \brief Create a code extractor for a sequence of blocks.
///
/// Given a sequence of basic blocks where the first block in the sequence
@ -91,14 +83,6 @@ template <typename T> class ArrayRef;
BlockFrequencyInfo *BFI = nullptr,
BranchProbabilityInfo *BPI = nullptr);
/// \brief Create a code extractor for a region node.
///
/// Behaves just like the generic code sequence constructor, but uses the
/// block sequence of the region node passed in.
CodeExtractor(DominatorTree &DT, const RegionNode &RN,
bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr,
BranchProbabilityInfo *BPI = nullptr);
/// \brief Perform the extraction, returning the new function.
///
/// Returns zero when called on a CodeExtractor instance where isEligible

View File

@ -59,6 +59,7 @@ struct YAMLXRaySledEntry {
yaml::Hex64 Function;
SledEntry::FunctionKinds Kind;
bool AlwaysInstrument;
std::string FunctionName;
};
/// The InstrumentationMap represents the computed function id's and indicated
@ -115,6 +116,7 @@ template <> struct MappingTraits<xray::YAMLXRaySledEntry> {
IO.mapRequired("function", Entry.Function);
IO.mapRequired("kind", Entry.Kind);
IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
IO.mapOptional("function-name", Entry.FunctionName);
}
static constexpr bool flow = true;

View File

@ -808,7 +808,7 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
// well. Or alternatively, replace all of this with inaccessiblememonly once
// that's implemented fully.
auto *Inst = CS.getInstruction();
if (isMallocLikeFn(Inst, &TLI) || isCallocLikeFn(Inst, &TLI)) {
if (isMallocOrCallocLikeFn(Inst, &TLI)) {
// Be conservative if the accessed pointer may alias the allocation -
// fallback to the generic handling below.
if (getBestAAResults().alias(MemoryLocation(Inst), Loc) == NoAlias)
@ -925,9 +925,8 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
const DataLayout &DL) {
assert(GEP1->getPointerOperand()->stripPointerCasts() ==
GEP2->getPointerOperand()->stripPointerCasts() &&
GEP1->getPointerOperand()->getType() ==
GEP2->getPointerOperand()->getType() &&
GEP2->getPointerOperand()->stripPointerCasts() &&
GEP1->getPointerOperandType() == GEP2->getPointerOperandType() &&
"Expected GEPs with the same pointer operand");
// Try to determine whether GEP1 and GEP2 index through arrays, into structs,
@ -1186,9 +1185,8 @@ AliasResult BasicAAResult::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size,
// just the same underlying object), see if that tells us anything about
// the resulting pointers.
if (GEP1->getPointerOperand()->stripPointerCasts() ==
GEP2->getPointerOperand()->stripPointerCasts() &&
GEP1->getPointerOperand()->getType() ==
GEP2->getPointerOperand()->getType()) {
GEP2->getPointerOperand()->stripPointerCasts() &&
GEP1->getPointerOperandType() == GEP2->getPointerOperandType()) {
AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL);
// If we couldn't find anything interesting, don't abandon just yet.
if (R != MayAlias)

View File

@ -72,6 +72,32 @@ static const uint32_t UR_TAKEN_WEIGHT = 1;
/// easily subsume it.
static const uint32_t UR_NONTAKEN_WEIGHT = 1024*1024 - 1;
/// \brief Returns the branch probability for unreachable edge according to
/// heuristic.
///
/// This is the branch probability being taken to a block that terminates
/// (eventually) in unreachable. These are predicted as unlikely as possible.
static BranchProbability getUnreachableProbability(uint64_t UnreachableCount) {
assert(UnreachableCount > 0 && "UnreachableCount must be > 0");
return BranchProbability::getBranchProbability(
UR_TAKEN_WEIGHT,
(UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) * UnreachableCount);
}
/// \brief Returns the branch probability for reachable edge according to
/// heuristic.
///
/// This is the branch probability not being taken toward a block that
/// terminates (eventually) in unreachable. Such a branch is essentially never
/// taken. Set the weight to an absurdly high value so that nested loops don't
/// easily subsume it.
static BranchProbability getReachableProbability(uint64_t ReachableCount) {
assert(ReachableCount > 0 && "ReachableCount must be > 0");
return BranchProbability::getBranchProbability(
UR_NONTAKEN_WEIGHT,
(UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) * ReachableCount);
}
/// \brief Weight for a branch taken going into a cold block.
///
/// This is the weight for a branch taken toward a block marked
@ -179,7 +205,11 @@ BranchProbabilityInfo::updatePostDominatedByColdCall(const BasicBlock *BB) {
/// unreachable-terminated block as extremely unlikely.
bool BranchProbabilityInfo::calcUnreachableHeuristics(const BasicBlock *BB) {
const TerminatorInst *TI = BB->getTerminator();
if (TI->getNumSuccessors() == 0)
assert(TI->getNumSuccessors() > 1 && "expected more than one successor!");
// Return false here so that edge weights for InvokeInst could be decided
// in calcInvokeHeuristics().
if (isa<InvokeInst>(TI))
return false;
SmallVector<unsigned, 4> UnreachableEdges;
@ -191,14 +221,8 @@ bool BranchProbabilityInfo::calcUnreachableHeuristics(const BasicBlock *BB) {
else
ReachableEdges.push_back(I.getSuccessorIndex());
// Skip probabilities if this block has a single successor or if all were
// reachable.
if (TI->getNumSuccessors() == 1 || UnreachableEdges.empty())
return false;
// Return false here so that edge weights for InvokeInst could be decided
// in calcInvokeHeuristics().
if (isa<InvokeInst>(TI))
// Skip probabilities if all were reachable.
if (UnreachableEdges.empty())
return false;
if (ReachableEdges.empty()) {
@ -208,12 +232,8 @@ bool BranchProbabilityInfo::calcUnreachableHeuristics(const BasicBlock *BB) {
return true;
}
auto UnreachableProb = BranchProbability::getBranchProbability(
UR_TAKEN_WEIGHT, (UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) *
uint64_t(UnreachableEdges.size()));
auto ReachableProb = BranchProbability::getBranchProbability(
UR_NONTAKEN_WEIGHT,
(UR_TAKEN_WEIGHT + UR_NONTAKEN_WEIGHT) * uint64_t(ReachableEdges.size()));
auto UnreachableProb = getUnreachableProbability(UnreachableEdges.size());
auto ReachableProb = getReachableProbability(ReachableEdges.size());
for (unsigned SuccIdx : UnreachableEdges)
setEdgeProbability(BB, SuccIdx, UnreachableProb);
@ -224,11 +244,12 @@ bool BranchProbabilityInfo::calcUnreachableHeuristics(const BasicBlock *BB) {
}
// Propagate existing explicit probabilities from either profile data or
// 'expect' intrinsic processing.
// 'expect' intrinsic processing. Examine metadata against unreachable
// heuristic. The probability of the edge coming to unreachable block is
// set to min of metadata and unreachable heuristic.
bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
const TerminatorInst *TI = BB->getTerminator();
if (TI->getNumSuccessors() == 1)
return false;
assert(TI->getNumSuccessors() > 1 && "expected more than one successor!");
if (!isa<BranchInst>(TI) && !isa<SwitchInst>(TI))
return false;
@ -249,6 +270,8 @@ bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
// be scaled to fit in 32 bits.
uint64_t WeightSum = 0;
SmallVector<uint32_t, 2> Weights;
SmallVector<unsigned, 2> UnreachableIdxs;
SmallVector<unsigned, 2> ReachableIdxs;
Weights.reserve(TI->getNumSuccessors());
for (unsigned i = 1, e = WeightsNode->getNumOperands(); i != e; ++i) {
ConstantInt *Weight =
@ -259,6 +282,10 @@ bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
"Too many bits for uint32_t");
Weights.push_back(Weight->getZExtValue());
WeightSum += Weights.back();
if (PostDominatedByUnreachable.count(TI->getSuccessor(i - 1)))
UnreachableIdxs.push_back(i - 1);
else
ReachableIdxs.push_back(i - 1);
}
assert(Weights.size() == TI->getNumSuccessors() && "Checked above");
@ -267,20 +294,52 @@ bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
uint64_t ScalingFactor =
(WeightSum > UINT32_MAX) ? WeightSum / UINT32_MAX + 1 : 1;
WeightSum = 0;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
Weights[i] /= ScalingFactor;
WeightSum += Weights[i];
if (ScalingFactor > 1) {
WeightSum = 0;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
Weights[i] /= ScalingFactor;
WeightSum += Weights[i];
}
}
if (WeightSum == 0) {
if (WeightSum == 0 || ReachableIdxs.size() == 0) {
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
setEdgeProbability(BB, i, {1, e});
} else {
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
setEdgeProbability(BB, i, {Weights[i], static_cast<uint32_t>(WeightSum)});
Weights[i] = 1;
WeightSum = TI->getNumSuccessors();
}
// Set the probability.
SmallVector<BranchProbability, 2> BP;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
BP.push_back({ Weights[i], static_cast<uint32_t>(WeightSum) });
// Examine the metadata against unreachable heuristic.
// If the unreachable heuristic is more strong then we use it for this edge.
if (UnreachableIdxs.size() > 0 && ReachableIdxs.size() > 0) {
auto ToDistribute = BranchProbability::getZero();
auto UnreachableProb = getUnreachableProbability(UnreachableIdxs.size());
for (auto i : UnreachableIdxs)
if (UnreachableProb < BP[i]) {
ToDistribute += BP[i] - UnreachableProb;
BP[i] = UnreachableProb;
}
// If we modified the probability of some edges then we must distribute
// the difference between reachable blocks.
if (ToDistribute > BranchProbability::getZero()) {
BranchProbability PerEdge = ToDistribute / ReachableIdxs.size();
for (auto i : ReachableIdxs) {
BP[i] += PerEdge;
ToDistribute -= PerEdge;
}
// Tail goes to the first reachable edge.
BP[ReachableIdxs[0]] += ToDistribute;
}
}
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
setEdgeProbability(BB, i, BP[i]);
assert(WeightSum <= UINT32_MAX &&
"Expected weights to scale down to 32 bits");
@ -297,7 +356,11 @@ bool BranchProbabilityInfo::calcMetadataWeights(const BasicBlock *BB) {
/// Return false, otherwise.
bool BranchProbabilityInfo::calcColdCallHeuristics(const BasicBlock *BB) {
const TerminatorInst *TI = BB->getTerminator();
if (TI->getNumSuccessors() == 0)
assert(TI->getNumSuccessors() > 1 && "expected more than one successor!");
// Return false here so that edge weights for InvokeInst could be decided
// in calcInvokeHeuristics().
if (isa<InvokeInst>(TI))
return false;
// Determine which successors are post-dominated by a cold block.
@ -309,13 +372,8 @@ bool BranchProbabilityInfo::calcColdCallHeuristics(const BasicBlock *BB) {
else
NormalEdges.push_back(I.getSuccessorIndex());
// Return false here so that edge weights for InvokeInst could be decided
// in calcInvokeHeuristics().
if (isa<InvokeInst>(TI))
return false;
// Skip probabilities if this block has a single successor.
if (TI->getNumSuccessors() == 1 || ColdEdges.empty())
// Skip probabilities if no cold edges.
if (ColdEdges.empty())
return false;
if (NormalEdges.empty()) {
@ -698,10 +756,13 @@ void BranchProbabilityInfo::calculate(const Function &F, const LoopInfo &LI) {
DEBUG(dbgs() << "Computing probabilities for " << BB->getName() << "\n");
updatePostDominatedByUnreachable(BB);
updatePostDominatedByColdCall(BB);
if (calcUnreachableHeuristics(BB))
// If there is no at least two successors, no sense to set probability.
if (BB->getTerminator()->getNumSuccessors() < 2)
continue;
if (calcMetadataWeights(BB))
continue;
if (calcUnreachableHeuristics(BB))
continue;
if (calcColdCallHeuristics(BB))
continue;
if (calcLoopBranchHeuristics(BB, LI))

View File

@ -400,8 +400,7 @@ template <typename CFLAA> class CFLGraphBuilder {
// TODO: address other common library functions such as realloc(),
// strdup(),
// etc.
if (isMallocLikeFn(Inst, &TLI) || isCallocLikeFn(Inst, &TLI) ||
isFreeCall(Inst, &TLI))
if (isMallocOrCallocLikeFn(Inst, &TLI) || isFreeCall(Inst, &TLI))
return;
// TODO: Add support for noalias args/all the other fun function

View File

@ -75,20 +75,16 @@ static Value *SimplifyXorInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyCastInst(unsigned, Value *, Type *,
const Query &, unsigned);
/// For a boolean type, or a vector of boolean type, return false, or
/// a vector with every element false, as appropriate for the type.
/// For a boolean type or a vector of boolean type, return false or a vector
/// with every element false.
static Constant *getFalse(Type *Ty) {
assert(Ty->getScalarType()->isIntegerTy(1) &&
"Expected i1 type or a vector of i1!");
return Constant::getNullValue(Ty);
return ConstantInt::getFalse(Ty);
}
/// For a boolean type, or a vector of boolean type, return true, or
/// a vector with every element true, as appropriate for the type.
/// For a boolean type or a vector of boolean type, return true or a vector
/// with every element true.
static Constant *getTrue(Type *Ty) {
assert(Ty->getScalarType()->isIntegerTy(1) &&
"Expected i1 type or a vector of i1!");
return Constant::getAllOnesValue(Ty);
return ConstantInt::getTrue(Ty);
}
/// isSameCompare - Is V equivalent to the comparison "LHS Pred RHS"?
@ -572,11 +568,11 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
match(Op1, m_Not(m_Specific(Op0))))
return Constant::getAllOnesValue(Ty);
// add nsw/nuw (xor Y, signbit), signbit --> Y
// add nsw/nuw (xor Y, signmask), signmask --> Y
// The no-wrapping add guarantees that the top bit will be set by the add.
// Therefore, the xor must be clearing the already set sign bit of Y.
if ((isNSW || isNUW) && match(Op1, m_SignBit()) &&
match(Op0, m_Xor(m_Value(Y), m_SignBit())))
if ((isNSW || isNUW) && match(Op1, m_SignMask()) &&
match(Op0, m_Xor(m_Value(Y), m_SignMask())))
return Y;
/// i1 add -> xor.
@ -1085,7 +1081,7 @@ static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
match(Op1, m_ConstantInt(C2))) {
bool Overflow;
C1->getValue().umul_ov(C2->getValue(), Overflow);
(void)C1->getValue().umul_ov(C2->getValue(), Overflow);
if (Overflow)
return Constant::getNullValue(Op0->getType());
}
@ -2823,7 +2819,7 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS,
return ConstantInt::getTrue(RHS->getContext());
}
}
if (CIVal->isSignBit() && *CI2Val == 1) {
if (CIVal->isSignMask() && *CI2Val == 1) {
if (Pred == ICmpInst::ICMP_UGT)
return ConstantInt::getFalse(RHS->getContext());
if (Pred == ICmpInst::ICMP_ULE)
@ -3800,6 +3796,8 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
Type *GEPTy = PointerType::get(LastType, AS);
if (VectorType *VT = dyn_cast<VectorType>(Ops[0]->getType()))
GEPTy = VectorType::get(GEPTy, VT->getNumElements());
else if (VectorType *VT = dyn_cast<VectorType>(Ops[1]->getType()))
GEPTy = VectorType::get(GEPTy, VT->getNumElements());
if (isa<UndefValue>(Ops[0]))
return UndefValue::get(GEPTy);
@ -4082,6 +4080,60 @@ Value *llvm::SimplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
RecursionLimit);
}
/// For the given destination element of a shuffle, peek through shuffles to
/// match a root vector source operand that contains that element in the same
/// vector lane (ie, the same mask index), so we can eliminate the shuffle(s).
static Value *foldIdentityShuffles(int DestElt, Value *Op0, Value *Op1,
Constant *Mask, Value *RootVec, int RootElt,
unsigned MaxRecurse) {
if (!MaxRecurse--)
return nullptr;
// Bail out if any mask value is undefined. That kind of shuffle may be
// simplified further based on demanded bits or other folds.
int MaskVal = ShuffleVectorInst::getMaskValue(Mask, RootElt);
if (MaskVal == -1)
return nullptr;
// The mask value chooses which source operand we need to look at next.
Value *SourceOp;
int InVecNumElts = Op0->getType()->getVectorNumElements();
if (MaskVal < InVecNumElts) {
RootElt = MaskVal;
SourceOp = Op0;
} else {
RootElt = MaskVal - InVecNumElts;
SourceOp = Op1;
}
// If the source operand is a shuffle itself, look through it to find the
// matching root vector.
if (auto *SourceShuf = dyn_cast<ShuffleVectorInst>(SourceOp)) {
return foldIdentityShuffles(
DestElt, SourceShuf->getOperand(0), SourceShuf->getOperand(1),
SourceShuf->getMask(), RootVec, RootElt, MaxRecurse);
}
// TODO: Look through bitcasts? What if the bitcast changes the vector element
// size?
// The source operand is not a shuffle. Initialize the root vector value for
// this shuffle if that has not been done yet.
if (!RootVec)
RootVec = SourceOp;
// Give up as soon as a source operand does not match the existing root value.
if (RootVec != SourceOp)
return nullptr;
// The element must be coming from the same lane in the source vector
// (although it may have crossed lanes in intermediate shuffles).
if (RootElt != DestElt)
return nullptr;
return RootVec;
}
static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
Type *RetTy, const Query &Q,
unsigned MaxRecurse) {
@ -4126,7 +4178,28 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
OpShuf->getMask()->getSplatValue())
return Op1;
return nullptr;
// Don't fold a shuffle with undef mask elements. This may get folded in a
// better way using demanded bits or other analysis.
// TODO: Should we allow this?
for (unsigned i = 0; i != MaskNumElts; ++i)
if (ShuffleVectorInst::getMaskValue(Mask, i) == -1)
return nullptr;
// Check if every element of this shuffle can be mapped back to the
// corresponding element of a single root vector. If so, we don't need this
// shuffle. This handles simple identity shuffles as well as chains of
// shuffles that may widen/narrow and/or move elements across lanes and back.
Value *RootVec = nullptr;
for (unsigned i = 0; i != MaskNumElts; ++i) {
// Note that recursion is limited for each vector element, so if any element
// exceeds the limit, this will fail to simplify.
RootVec = foldIdentityShuffles(i, Op0, Op1, Mask, RootVec, i, MaxRecurse);
// We can't replace a widening/narrowing shuffle with one of its operands.
if (!RootVec || RootVec->getType() != RetTy)
return nullptr;
}
return RootVec;
}
/// Given operands for a ShuffleVectorInst, fold the result or return null.

View File

@ -37,6 +37,7 @@ enum AllocType : uint8_t {
CallocLike = 1<<2, // allocates + bzero
ReallocLike = 1<<3, // reallocates
StrDupLike = 1<<4,
MallocOrCallocLike = MallocLike | CallocLike,
AllocLike = MallocLike | CallocLike | StrDupLike,
AnyAlloc = AllocLike | ReallocLike
};
@ -77,8 +78,8 @@ static const std::pair<LibFunc, AllocFnsTy> AllocationFnData[] = {
// TODO: Handle "int posix_memalign(void **, size_t, size_t)"
};
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast,
bool &IsNoBuiltin) {
static const Function *getCalledFunction(const Value *V, bool LookThroughBitCast,
bool &IsNoBuiltin) {
// Don't care about intrinsics in this case.
if (isa<IntrinsicInst>(V))
return nullptr;
@ -86,13 +87,13 @@ static Function *getCalledFunction(const Value *V, bool LookThroughBitCast,
if (LookThroughBitCast)
V = V->stripPointerCasts();
CallSite CS(const_cast<Value*>(V));
ImmutableCallSite CS(V);
if (!CS.getInstruction())
return nullptr;
IsNoBuiltin = CS.isNoBuiltin();
Function *Callee = CS.getCalledFunction();
const Function *Callee = CS.getCalledFunction();
if (!Callee || !Callee->isDeclaration())
return nullptr;
return Callee;
@ -219,6 +220,14 @@ bool llvm::isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
return getAllocationData(V, CallocLike, TLI, LookThroughBitCast).hasValue();
}
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory similiar to malloc or calloc.
bool llvm::isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
bool LookThroughBitCast) {
return getAllocationData(V, MallocOrCallocLike, TLI,
LookThroughBitCast).hasValue();
}
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,

View File

@ -1291,7 +1291,6 @@ void MemorySSA::buildMemorySSA() {
// could just look up the memory access for every possible instruction in the
// stream.
SmallPtrSet<BasicBlock *, 32> DefiningBlocks;
SmallPtrSet<BasicBlock *, 32> DefUseBlocks;
// Go through each block, figure out where defs occur, and chain together all
// the accesses.
for (BasicBlock &B : F) {
@ -1316,8 +1315,6 @@ void MemorySSA::buildMemorySSA() {
}
if (InsertIntoDef)
DefiningBlocks.insert(&B);
if (Accesses)
DefUseBlocks.insert(&B);
}
placePHINodes(DefiningBlocks, BBNumbers);

View File

@ -1093,7 +1093,7 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
APInt Mult(W, i);
unsigned TwoFactors = Mult.countTrailingZeros();
T += TwoFactors;
Mult = Mult.lshr(TwoFactors);
Mult.lshrInPlace(TwoFactors);
OddFactorial *= Mult;
}
@ -1276,7 +1276,8 @@ static const SCEV *getUnsignedOverflowLimitForStep(const SCEV *Step,
namespace {
struct ExtendOpTraitsBase {
typedef const SCEV *(ScalarEvolution::*GetExtendExprTy)(const SCEV *, Type *);
typedef const SCEV *(ScalarEvolution::*GetExtendExprTy)(
const SCEV *, Type *, ScalarEvolution::ExtendCacheTy &Cache);
};
// Used to make code generic over signed and unsigned overflow.
@ -1305,8 +1306,9 @@ struct ExtendOpTraits<SCEVSignExtendExpr> : public ExtendOpTraitsBase {
}
};
const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
SCEVSignExtendExpr>::GetExtendExpr = &ScalarEvolution::getSignExtendExpr;
const ExtendOpTraitsBase::GetExtendExprTy
ExtendOpTraits<SCEVSignExtendExpr>::GetExtendExpr =
&ScalarEvolution::getSignExtendExprCached;
template <>
struct ExtendOpTraits<SCEVZeroExtendExpr> : public ExtendOpTraitsBase {
@ -1321,8 +1323,9 @@ struct ExtendOpTraits<SCEVZeroExtendExpr> : public ExtendOpTraitsBase {
}
};
const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
SCEVZeroExtendExpr>::GetExtendExpr = &ScalarEvolution::getZeroExtendExpr;
const ExtendOpTraitsBase::GetExtendExprTy
ExtendOpTraits<SCEVZeroExtendExpr>::GetExtendExpr =
&ScalarEvolution::getZeroExtendExprCached;
}
// The recurrence AR has been shown to have no signed/unsigned wrap or something
@ -1334,7 +1337,8 @@ const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
// "sext/zext(PostIncAR)"
template <typename ExtendOpTy>
static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
ScalarEvolution *SE) {
ScalarEvolution *SE,
ScalarEvolution::ExtendCacheTy &Cache) {
auto WrapType = ExtendOpTraits<ExtendOpTy>::WrapType;
auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;
@ -1381,9 +1385,9 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
unsigned BitWidth = SE->getTypeSizeInBits(AR->getType());
Type *WideTy = IntegerType::get(SE->getContext(), BitWidth * 2);
const SCEV *OperandExtendedStart =
SE->getAddExpr((SE->*GetExtendExpr)(PreStart, WideTy),
(SE->*GetExtendExpr)(Step, WideTy));
if ((SE->*GetExtendExpr)(Start, WideTy) == OperandExtendedStart) {
SE->getAddExpr((SE->*GetExtendExpr)(PreStart, WideTy, Cache),
(SE->*GetExtendExpr)(Step, WideTy, Cache));
if ((SE->*GetExtendExpr)(Start, WideTy, Cache) == OperandExtendedStart) {
if (PreAR && AR->getNoWrapFlags(WrapType)) {
// If we know `AR` == {`PreStart`+`Step`,+,`Step`} is `WrapType` (FlagNSW
// or FlagNUW) and that `PreStart` + `Step` is `WrapType` too, then
@ -1408,15 +1412,17 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
// Get the normalized zero or sign extended expression for this AddRec's Start.
template <typename ExtendOpTy>
static const SCEV *getExtendAddRecStart(const SCEVAddRecExpr *AR, Type *Ty,
ScalarEvolution *SE) {
ScalarEvolution *SE,
ScalarEvolution::ExtendCacheTy &Cache) {
auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;
const SCEV *PreStart = getPreStartForExtend<ExtendOpTy>(AR, Ty, SE);
const SCEV *PreStart = getPreStartForExtend<ExtendOpTy>(AR, Ty, SE, Cache);
if (!PreStart)
return (SE->*GetExtendExpr)(AR->getStart(), Ty);
return (SE->*GetExtendExpr)(AR->getStart(), Ty, Cache);
return SE->getAddExpr((SE->*GetExtendExpr)(AR->getStepRecurrence(*SE), Ty),
(SE->*GetExtendExpr)(PreStart, Ty));
return SE->getAddExpr(
(SE->*GetExtendExpr)(AR->getStepRecurrence(*SE), Ty, Cache),
(SE->*GetExtendExpr)(PreStart, Ty, Cache));
}
// Try to prove away overflow by looking at "nearby" add recurrences. A
@ -1496,8 +1502,31 @@ bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
return false;
}
const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
Type *Ty) {
const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty) {
// Use the local cache to prevent exponential behavior of
// getZeroExtendExprImpl.
ExtendCacheTy Cache;
return getZeroExtendExprCached(Op, Ty, Cache);
}
/// Query \p Cache before calling getZeroExtendExprImpl. If there is no
/// related entry in the \p Cache, call getZeroExtendExprImpl and save
/// the result in the \p Cache.
const SCEV *ScalarEvolution::getZeroExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache) {
auto It = Cache.find({Op, Ty});
if (It != Cache.end())
return It->second;
const SCEV *ZExt = getZeroExtendExprImpl(Op, Ty, Cache);
auto InsertResult = Cache.insert({{Op, Ty}, ZExt});
assert(InsertResult.second && "Expect the key was not in the cache");
(void)InsertResult;
return ZExt;
}
/// The real implementation of getZeroExtendExpr.
const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache) {
assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
"This is not an extending conversion!");
assert(isSCEVable(Ty) &&
@ -1507,11 +1536,11 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
// Fold if the operand is constant.
if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
return getConstant(
cast<ConstantInt>(ConstantExpr::getZExt(SC->getValue(), Ty)));
cast<ConstantInt>(ConstantExpr::getZExt(SC->getValue(), Ty)));
// zext(zext(x)) --> zext(x)
if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
return getZeroExtendExpr(SZ->getOperand(), Ty);
return getZeroExtendExprCached(SZ->getOperand(), Ty, Cache);
// Before doing any expensive analysis, check to see if we've already
// computed a SCEV for this Op and Ty.
@ -1555,8 +1584,8 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
// we don't need to do any further analysis.
if (AR->hasNoUnsignedWrap())
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getZeroExtendExprCached(Step, Ty, Cache), L, AR->getNoWrapFlags());
// Check whether the backedge-taken count is SCEVCouldNotCompute.
// Note that this serves two purposes: It filters out loops that are
@ -1581,21 +1610,22 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
// Check whether Start+Step*MaxBECount has no unsigned overflow.
const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step);
const SCEV *ZAdd = getZeroExtendExpr(getAddExpr(Start, ZMul), WideTy);
const SCEV *WideStart = getZeroExtendExpr(Start, WideTy);
const SCEV *ZAdd =
getZeroExtendExprCached(getAddExpr(Start, ZMul), WideTy, Cache);
const SCEV *WideStart = getZeroExtendExprCached(Start, WideTy, Cache);
const SCEV *WideMaxBECount =
getZeroExtendExpr(CastedMaxBECount, WideTy);
const SCEV *OperandExtendedAdd =
getAddExpr(WideStart,
getMulExpr(WideMaxBECount,
getZeroExtendExpr(Step, WideTy)));
getZeroExtendExprCached(CastedMaxBECount, WideTy, Cache);
const SCEV *OperandExtendedAdd = getAddExpr(
WideStart, getMulExpr(WideMaxBECount, getZeroExtendExprCached(
Step, WideTy, Cache)));
if (ZAdd == OperandExtendedAdd) {
// Cache knowledge of AR NUW, which is propagated to this AddRec.
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNUW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getZeroExtendExprCached(Step, Ty, Cache), L,
AR->getNoWrapFlags());
}
// Similar to above, only this time treat the step value as signed.
// This covers loops that count down.
@ -1609,7 +1639,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
}
}
@ -1641,8 +1671,9 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNUW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getZeroExtendExprCached(Step, Ty, Cache), L,
AR->getNoWrapFlags());
}
} else if (isKnownNegative(Step)) {
const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) -
@ -1657,7 +1688,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
}
}
@ -1666,8 +1697,8 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
if (proveNoWrapByVaryingStart<SCEVZeroExtendExpr>(Start, Step, L)) {
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNUW);
return getAddRecExpr(
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this),
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Cache),
getZeroExtendExprCached(Step, Ty, Cache), L, AR->getNoWrapFlags());
}
}
@ -1678,7 +1709,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
// commute the zero extension with the addition operation.
SmallVector<const SCEV *, 4> Ops;
for (const auto *Op : SA->operands())
Ops.push_back(getZeroExtendExpr(Op, Ty));
Ops.push_back(getZeroExtendExprCached(Op, Ty, Cache));
return getAddExpr(Ops, SCEV::FlagNUW);
}
}
@ -1692,8 +1723,31 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
return S;
}
const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
Type *Ty) {
const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty) {
// Use the local cache to prevent exponential behavior of
// getSignExtendExprImpl.
ExtendCacheTy Cache;
return getSignExtendExprCached(Op, Ty, Cache);
}
/// Query \p Cache before calling getSignExtendExprImpl. If there is no
/// related entry in the \p Cache, call getSignExtendExprImpl and save
/// the result in the \p Cache.
const SCEV *ScalarEvolution::getSignExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache) {
auto It = Cache.find({Op, Ty});
if (It != Cache.end())
return It->second;
const SCEV *SExt = getSignExtendExprImpl(Op, Ty, Cache);
auto InsertResult = Cache.insert({{Op, Ty}, SExt});
assert(InsertResult.second && "Expect the key was not in the cache");
(void)InsertResult;
return SExt;
}
/// The real implementation of getSignExtendExpr.
const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache) {
assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
"This is not an extending conversion!");
assert(isSCEVable(Ty) &&
@ -1703,11 +1757,11 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
// Fold if the operand is constant.
if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
return getConstant(
cast<ConstantInt>(ConstantExpr::getSExt(SC->getValue(), Ty)));
cast<ConstantInt>(ConstantExpr::getSExt(SC->getValue(), Ty)));
// sext(sext(x)) --> sext(x)
if (const SCEVSignExtendExpr *SS = dyn_cast<SCEVSignExtendExpr>(Op))
return getSignExtendExpr(SS->getOperand(), Ty);
return getSignExtendExprCached(SS->getOperand(), Ty, Cache);
// sext(zext(x)) --> zext(x)
if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
@ -1746,8 +1800,8 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
const APInt &C2 = SC2->getAPInt();
if (C1.isStrictlyPositive() && C2.isStrictlyPositive() &&
C2.ugt(C1) && C2.isPowerOf2())
return getAddExpr(getSignExtendExpr(SC1, Ty),
getSignExtendExpr(SMul, Ty));
return getAddExpr(getSignExtendExprCached(SC1, Ty, Cache),
getSignExtendExprCached(SMul, Ty, Cache));
}
}
}
@ -1758,7 +1812,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
// commute the sign extension with the addition operation.
SmallVector<const SCEV *, 4> Ops;
for (const auto *Op : SA->operands())
Ops.push_back(getSignExtendExpr(Op, Ty));
Ops.push_back(getSignExtendExprCached(Op, Ty, Cache));
return getAddExpr(Ops, SCEV::FlagNSW);
}
}
@ -1782,8 +1836,8 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
// we don't need to do any further analysis.
if (AR->hasNoSignedWrap())
return getAddRecExpr(
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this),
getSignExtendExpr(Step, Ty), L, SCEV::FlagNSW);
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Cache),
getSignExtendExprCached(Step, Ty, Cache), L, SCEV::FlagNSW);
// Check whether the backedge-taken count is SCEVCouldNotCompute.
// Note that this serves two purposes: It filters out loops that are
@ -1808,21 +1862,22 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
// Check whether Start+Step*MaxBECount has no signed overflow.
const SCEV *SMul = getMulExpr(CastedMaxBECount, Step);
const SCEV *SAdd = getSignExtendExpr(getAddExpr(Start, SMul), WideTy);
const SCEV *WideStart = getSignExtendExpr(Start, WideTy);
const SCEV *SAdd =
getSignExtendExprCached(getAddExpr(Start, SMul), WideTy, Cache);
const SCEV *WideStart = getSignExtendExprCached(Start, WideTy, Cache);
const SCEV *WideMaxBECount =
getZeroExtendExpr(CastedMaxBECount, WideTy);
const SCEV *OperandExtendedAdd =
getAddExpr(WideStart,
getMulExpr(WideMaxBECount,
getSignExtendExpr(Step, WideTy)));
getZeroExtendExpr(CastedMaxBECount, WideTy);
const SCEV *OperandExtendedAdd = getAddExpr(
WideStart, getMulExpr(WideMaxBECount, getSignExtendExprCached(
Step, WideTy, Cache)));
if (SAdd == OperandExtendedAdd) {
// Cache knowledge of AR NSW, which is propagated to this AddRec.
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this),
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Cache),
getSignExtendExprCached(Step, Ty, Cache), L,
AR->getNoWrapFlags());
}
// Similar to above, only this time treat the step value as unsigned.
// This covers loops that count up with an unsigned step.
@ -1843,7 +1898,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
// Return the expression with the addrec on the outside.
return getAddRecExpr(
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this),
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Cache),
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
}
}
@ -1875,8 +1930,9 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
// Cache knowledge of AR NSW, then propagate NSW to the wide AddRec.
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
return getAddRecExpr(
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this),
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Cache),
getSignExtendExprCached(Step, Ty, Cache), L,
AR->getNoWrapFlags());
}
}
@ -1890,18 +1946,18 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
const APInt &C2 = SC2->getAPInt();
if (C1.isStrictlyPositive() && C2.isStrictlyPositive() && C2.ugt(C1) &&
C2.isPowerOf2()) {
Start = getSignExtendExpr(Start, Ty);
Start = getSignExtendExprCached(Start, Ty, Cache);
const SCEV *NewAR = getAddRecExpr(getZero(AR->getType()), Step, L,
AR->getNoWrapFlags());
return getAddExpr(Start, getSignExtendExpr(NewAR, Ty));
return getAddExpr(Start, getSignExtendExprCached(NewAR, Ty, Cache));
}
}
if (proveNoWrapByVaryingStart<SCEVSignExtendExpr>(Start, Step, L)) {
const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNSW);
return getAddRecExpr(
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this),
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Cache),
getSignExtendExprCached(Step, Ty, Cache), L, AR->getNoWrapFlags());
}
}
@ -3951,9 +4007,9 @@ static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) {
case Instruction::Xor:
if (auto *RHSC = dyn_cast<ConstantInt>(Op->getOperand(1)))
// If the RHS of the xor is a signbit, then this is just an add.
// Instcombine turns add of signbit into xor as a strength reduction step.
if (RHSC->getValue().isSignBit())
// If the RHS of the xor is a signmask, then this is just an add.
// Instcombine turns add of signmask into xor as a strength reduction step.
if (RHSC->getValue().isSignMask())
return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1));
return BinaryOp(Op);
@ -5272,28 +5328,12 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
break;
case Instruction::Or:
// If the RHS of the Or is a constant, we may have something like:
// X*4+1 which got turned into X*4|1. Handle this as an Add so loop
// optimizations will transparently handle this case.
//
// In order for this transformation to be safe, the LHS must be of the
// form X*(2^n) and the Or constant must be less than 2^n.
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->RHS)) {
const SCEV *LHS = getSCEV(BO->LHS);
const APInt &CIVal = CI->getValue();
if (GetMinTrailingZeros(LHS) >=
(CIVal.getBitWidth() - CIVal.countLeadingZeros())) {
// Build a plain add SCEV.
const SCEV *S = getAddExpr(LHS, getSCEV(CI));
// If the LHS of the add was an addrec and it has no-wrap flags,
// transfer the no-wrap flags, since an or won't introduce a wrap.
if (const SCEVAddRecExpr *NewAR = dyn_cast<SCEVAddRecExpr>(S)) {
const SCEVAddRecExpr *OldAR = cast<SCEVAddRecExpr>(LHS);
const_cast<SCEVAddRecExpr *>(NewAR)->setNoWrapFlags(
OldAR->getNoWrapFlags());
}
return S;
}
// Use ValueTracking to check whether this is actually an add.
if (haveNoCommonBitsSet(BO->LHS, BO->RHS, getDataLayout(), &AC,
nullptr, &DT)) {
// There aren't any common bits set, so the add can't wrap.
auto Flags = SCEV::NoWrapFlags(SCEV::FlagNUW | SCEV::FlagNSW);
return getAddExpr(getSCEV(BO->LHS), getSCEV(BO->RHS), Flags);
}
break;
@ -5329,7 +5369,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
// using an add, which is equivalent, and re-apply the zext.
APInt Trunc = CI->getValue().trunc(Z0TySize);
if (Trunc.zext(getTypeSizeInBits(UTy)) == CI->getValue() &&
Trunc.isSignBit())
Trunc.isSignMask())
return getZeroExtendExpr(getAddExpr(Z0, getConstant(Trunc)),
UTy);
}

View File

@ -292,15 +292,15 @@ static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
KnownOne = PossibleSumOne & Known;
// Are we still trying to solve for the sign bit?
if (!Known.isNegative()) {
if (!Known.isSignBitSet()) {
if (NSW) {
// Adding two non-negative numbers, or subtracting a negative number from
// a non-negative one, can't wrap into negative.
if (LHSKnownZero.isNegative() && KnownZero2.isNegative())
if (LHSKnownZero.isSignBitSet() && KnownZero2.isSignBitSet())
KnownZero.setSignBit();
// Adding two negative numbers, or subtracting a non-negative number from
// a negative one, can't wrap into non-negative.
else if (LHSKnownOne.isNegative() && KnownOne2.isNegative())
else if (LHSKnownOne.isSignBitSet() && KnownOne2.isSignBitSet())
KnownOne.setSignBit();
}
}
@ -322,10 +322,10 @@ static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
// The product of a number with itself is non-negative.
isKnownNonNegative = true;
} else {
bool isKnownNonNegativeOp1 = KnownZero.isNegative();
bool isKnownNonNegativeOp0 = KnownZero2.isNegative();
bool isKnownNegativeOp1 = KnownOne.isNegative();
bool isKnownNegativeOp0 = KnownOne2.isNegative();
bool isKnownNonNegativeOp1 = KnownZero.isSignBitSet();
bool isKnownNonNegativeOp0 = KnownZero2.isSignBitSet();
bool isKnownNegativeOp1 = KnownOne.isSignBitSet();
bool isKnownNegativeOp0 = KnownOne2.isSignBitSet();
// The product of two numbers with the same sign is non-negative.
isKnownNonNegative = (isKnownNegativeOp1 && isKnownNegativeOp0) ||
(isKnownNonNegativeOp1 && isKnownNonNegativeOp0);
@ -361,9 +361,9 @@ static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
// which case we prefer to follow the result of the direct computation,
// though as the program is invoking undefined behaviour we can choose
// whatever we like here.
if (isKnownNonNegative && !KnownOne.isNegative())
if (isKnownNonNegative && !KnownOne.isSignBitSet())
KnownZero.setSignBit();
else if (isKnownNegative && !KnownZero.isNegative())
else if (isKnownNegative && !KnownZero.isSignBitSet())
KnownOne.setSignBit();
}
@ -661,8 +661,10 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
// For those bits in RHS that are known, we can propagate them to known
// bits in V shifted to the right by C.
KnownZero |= RHSKnownZero.lshr(C->getZExtValue());
KnownOne |= RHSKnownOne.lshr(C->getZExtValue());
RHSKnownZero.lshrInPlace(C->getZExtValue());
KnownZero |= RHSKnownZero;
RHSKnownOne.lshrInPlace(C->getZExtValue());
KnownOne |= RHSKnownOne;
// assume(~(v << c) = a)
} else if (match(Arg, m_c_ICmp(Pred, m_Not(m_Shl(m_V, m_ConstantInt(C))),
m_Value(A))) &&
@ -672,8 +674,10 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
// For those bits in RHS that are known, we can propagate them inverted
// to known bits in V shifted to the right by C.
KnownZero |= RHSKnownOne.lshr(C->getZExtValue());
KnownOne |= RHSKnownZero.lshr(C->getZExtValue());
RHSKnownOne.lshrInPlace(C->getZExtValue());
KnownZero |= RHSKnownOne;
RHSKnownZero.lshrInPlace(C->getZExtValue());
KnownOne |= RHSKnownZero;
// assume(v >> c = a)
} else if (match(Arg,
m_c_ICmp(Pred, m_CombineOr(m_LShr(m_V, m_ConstantInt(C)),
@ -707,7 +711,7 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
APInt RHSKnownZero(BitWidth, 0), RHSKnownOne(BitWidth, 0);
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
if (RHSKnownZero.isNegative()) {
if (RHSKnownZero.isSignBitSet()) {
// We know that the sign bit is zero.
KnownZero.setSignBit();
}
@ -718,7 +722,7 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
APInt RHSKnownZero(BitWidth, 0), RHSKnownOne(BitWidth, 0);
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
if (RHSKnownOne.isAllOnesValue() || RHSKnownZero.isNegative()) {
if (RHSKnownOne.isAllOnesValue() || RHSKnownZero.isSignBitSet()) {
// We know that the sign bit is zero.
KnownZero.setSignBit();
}
@ -729,7 +733,7 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
APInt RHSKnownZero(BitWidth, 0), RHSKnownOne(BitWidth, 0);
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
if (RHSKnownOne.isNegative()) {
if (RHSKnownOne.isSignBitSet()) {
// We know that the sign bit is one.
KnownOne.setSignBit();
}
@ -740,7 +744,7 @@ static void computeKnownBitsFromAssume(const Value *V, APInt &KnownZero,
APInt RHSKnownZero(BitWidth, 0), RHSKnownOne(BitWidth, 0);
computeKnownBits(A, RHSKnownZero, RHSKnownOne, Depth+1, Query(Q, I));
if (RHSKnownZero.isAllOnesValue() || RHSKnownOne.isNegative()) {
if (RHSKnownZero.isAllOnesValue() || RHSKnownOne.isSignBitSet()) {
// We know that the sign bit is one.
KnownOne.setSignBit();
}
@ -990,23 +994,23 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
unsigned MaxHighZeros = 0;
if (SPF == SPF_SMAX) {
// If both sides are negative, the result is negative.
if (KnownOne.isNegative() && KnownOne2.isNegative())
if (KnownOne.isSignBitSet() && KnownOne2.isSignBitSet())
// We can derive a lower bound on the result by taking the max of the
// leading one bits.
MaxHighOnes =
std::max(KnownOne.countLeadingOnes(), KnownOne2.countLeadingOnes());
// If either side is non-negative, the result is non-negative.
else if (KnownZero.isNegative() || KnownZero2.isNegative())
else if (KnownZero.isSignBitSet() || KnownZero2.isSignBitSet())
MaxHighZeros = 1;
} else if (SPF == SPF_SMIN) {
// If both sides are non-negative, the result is non-negative.
if (KnownZero.isNegative() && KnownZero2.isNegative())
if (KnownZero.isSignBitSet() && KnownZero2.isSignBitSet())
// We can derive an upper bound on the result by taking the max of the
// leading zero bits.
MaxHighZeros = std::max(KnownZero.countLeadingOnes(),
KnownZero2.countLeadingOnes());
// If either side is negative, the result is negative.
else if (KnownOne.isNegative() || KnownOne2.isNegative())
else if (KnownOne.isSignBitSet() || KnownOne2.isSignBitSet())
MaxHighOnes = 1;
} else if (SPF == SPF_UMAX) {
// We can derive a lower bound on the result by taking the max of the
@ -1092,14 +1096,14 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
KZResult.setLowBits(ShiftAmt); // Low bits known 0.
// If this shift has "nsw" keyword, then the result is either a poison
// value or has the same sign bit as the first operand.
if (NSW && KnownZero.isNegative())
if (NSW && KnownZero.isSignBitSet())
KZResult.setSignBit();
return KZResult;
};
auto KOF = [NSW](const APInt &KnownOne, unsigned ShiftAmt) {
APInt KOResult = KnownOne << ShiftAmt;
if (NSW && KnownOne.isNegative())
if (NSW && KnownOne.isSignBitSet())
KOResult.setSignBit();
return KOResult;
};
@ -1111,10 +1115,11 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
}
case Instruction::LShr: {
// (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
auto KZF = [BitWidth](const APInt &KnownZero, unsigned ShiftAmt) {
return KnownZero.lshr(ShiftAmt) |
// High bits known zero.
APInt::getHighBitsSet(BitWidth, ShiftAmt);
auto KZF = [](const APInt &KnownZero, unsigned ShiftAmt) {
APInt KZResult = KnownZero.lshr(ShiftAmt);
// High bits known zero.
KZResult.setHighBits(ShiftAmt);
return KZResult;
};
auto KOF = [](const APInt &KnownOne, unsigned ShiftAmt) {
@ -1169,28 +1174,25 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
// If the first operand is non-negative or has all low bits zero, then
// the upper bits are all zero.
if (KnownZero2.isNegative() || ((KnownZero2 & LowBits) == LowBits))
if (KnownZero2.isSignBitSet() || ((KnownZero2 & LowBits) == LowBits))
KnownZero |= ~LowBits;
// If the first operand is negative and not all low bits are zero, then
// the upper bits are all one.
if (KnownOne2.isNegative() && ((KnownOne2 & LowBits) != 0))
if (KnownOne2.isSignBitSet() && ((KnownOne2 & LowBits) != 0))
KnownOne |= ~LowBits;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
break;
}
}
// The sign bit is the LHS's sign bit, except when the result of the
// remainder is zero.
if (KnownZero.isNonNegative()) {
APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0);
computeKnownBits(I->getOperand(0), LHSKnownZero, LHSKnownOne, Depth + 1,
Q);
// If it's known zero, our sign bit is also zero.
if (LHSKnownZero.isNegative())
KnownZero.setSignBit();
}
computeKnownBits(I->getOperand(0), KnownZero2, KnownOne2, Depth + 1, Q);
// If it's known zero, our sign bit is also zero.
if (KnownZero2.isSignBitSet())
KnownZero.setSignBit();
break;
case Instruction::URem: {
@ -1331,24 +1333,24 @@ static void computeKnownBitsFromOperator(const Operator *I, APInt &KnownZero,
// (add non-negative, non-negative) --> non-negative
// (add negative, negative) --> negative
if (Opcode == Instruction::Add) {
if (KnownZero2.isNegative() && KnownZero3.isNegative())
if (KnownZero2.isSignBitSet() && KnownZero3.isSignBitSet())
KnownZero.setSignBit();
else if (KnownOne2.isNegative() && KnownOne3.isNegative())
else if (KnownOne2.isSignBitSet() && KnownOne3.isSignBitSet())
KnownOne.setSignBit();
}
// (sub nsw non-negative, negative) --> non-negative
// (sub nsw negative, non-negative) --> negative
else if (Opcode == Instruction::Sub && LL == I) {
if (KnownZero2.isNegative() && KnownOne3.isNegative())
if (KnownZero2.isSignBitSet() && KnownOne3.isSignBitSet())
KnownZero.setSignBit();
else if (KnownOne2.isNegative() && KnownZero3.isNegative())
else if (KnownOne2.isSignBitSet() && KnownZero3.isSignBitSet())
KnownOne.setSignBit();
}
// (mul nsw non-negative, non-negative) --> non-negative
else if (Opcode == Instruction::Mul && KnownZero2.isNegative() &&
KnownZero3.isNegative())
else if (Opcode == Instruction::Mul && KnownZero2.isSignBitSet() &&
KnownZero3.isSignBitSet())
KnownZero.setSignBit();
}
@ -1614,8 +1616,8 @@ void ComputeSignBit(const Value *V, bool &KnownZero, bool &KnownOne,
APInt ZeroBits(BitWidth, 0);
APInt OneBits(BitWidth, 0);
computeKnownBits(V, ZeroBits, OneBits, Depth, Q);
KnownOne = OneBits.isNegative();
KnownZero = ZeroBits.isNegative();
KnownOne = OneBits.isSignBitSet();
KnownZero = ZeroBits.isSignBitSet();
}
/// Return true if the given value is known to have exactly one
@ -1638,9 +1640,9 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
if (match(V, m_Shl(m_One(), m_Value())))
return true;
// (signbit) >>l X is clearly a power of two if the one is not shifted off the
// bottom. If it is shifted off the bottom then the result is undefined.
if (match(V, m_LShr(m_SignBit(), m_Value())))
// (signmask) >>l X is clearly a power of two if the one is not shifted off
// the bottom. If it is shifted off the bottom then the result is undefined.
if (match(V, m_LShr(m_SignMask(), m_Value())))
return true;
// The remaining tests are all recursive, so bail out if we hit the limit.
@ -2241,7 +2243,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth,
// If we are subtracting one from a positive number, there is no carry
// out of the result.
if (KnownZero.isNegative())
if (KnownZero.isSignBitSet())
return Tmp;
}
@ -2265,7 +2267,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth,
// If the input is known to be positive (the sign bit is known clear),
// the output of the NEG has the same number of sign bits as the input.
if (KnownZero.isNegative())
if (KnownZero.isSignBitSet())
return Tmp2;
// Otherwise, we treat this like a SUB.
@ -2322,10 +2324,10 @@ static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth,
// If we know that the sign bit is either zero or one, determine the number of
// identical bits in the top of the input value.
if (KnownZero.isNegative())
if (KnownZero.isSignBitSet())
return std::max(FirstAnswer, KnownZero.countLeadingOnes());
if (KnownOne.isNegative())
if (KnownOne.isSignBitSet())
return std::max(FirstAnswer, KnownOne.countLeadingOnes());
// computeKnownBits gave us no extra information about the top bits.
@ -3556,14 +3558,14 @@ OverflowResult llvm::computeOverflowForUnsignedMul(const Value *LHS,
// We know the multiply operation doesn't overflow if the maximum values for
// each operand will not overflow after we multiply them together.
bool MaxOverflow;
LHSMax.umul_ov(RHSMax, MaxOverflow);
(void)LHSMax.umul_ov(RHSMax, MaxOverflow);
if (!MaxOverflow)
return OverflowResult::NeverOverflows;
// We know it always overflows if multiplying the smallest possible values for
// the operands also results in overflow.
bool MinOverflow;
LHSKnownOne.umul_ov(RHSKnownOne, MinOverflow);
(void)LHSKnownOne.umul_ov(RHSKnownOne, MinOverflow);
if (MinOverflow)
return OverflowResult::AlwaysOverflows;

View File

@ -143,27 +143,24 @@ bool LLParser::ValidateEndOfModule() {
FnAttrs.removeAttribute(Attribute::Alignment);
}
AS = AS.addAttributes(
Context, AttributeList::FunctionIndex,
AttributeList::get(Context, AttributeList::FunctionIndex, FnAttrs));
AS = AS.addAttributes(Context, AttributeList::FunctionIndex,
AttributeSet::get(Context, FnAttrs));
Fn->setAttributes(AS);
} else if (CallInst *CI = dyn_cast<CallInst>(V)) {
AttributeList AS = CI->getAttributes();
AttrBuilder FnAttrs(AS.getFnAttributes());
AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
FnAttrs.merge(B);
AS = AS.addAttributes(
Context, AttributeList::FunctionIndex,
AttributeList::get(Context, AttributeList::FunctionIndex, FnAttrs));
AS = AS.addAttributes(Context, AttributeList::FunctionIndex,
AttributeSet::get(Context, FnAttrs));
CI->setAttributes(AS);
} else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) {
AttributeList AS = II->getAttributes();
AttrBuilder FnAttrs(AS.getFnAttributes());
AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
FnAttrs.merge(B);
AS = AS.addAttributes(
Context, AttributeList::FunctionIndex,
AttributeList::get(Context, AttributeList::FunctionIndex, FnAttrs));
AS = AS.addAttributes(Context, AttributeList::FunctionIndex,
AttributeSet::get(Context, FnAttrs));
II->setAttributes(AS);
} else {
llvm_unreachable("invalid object with forward attribute group reference");

View File

@ -372,15 +372,27 @@ Expected<std::string> readTriple(BitstreamCursor &Stream) {
class BitcodeReaderBase {
protected:
BitcodeReaderBase(BitstreamCursor Stream) : Stream(std::move(Stream)) {
BitcodeReaderBase(BitstreamCursor Stream, StringRef Strtab)
: Stream(std::move(Stream)), Strtab(Strtab) {
this->Stream.setBlockInfo(&BlockInfo);
}
BitstreamBlockInfo BlockInfo;
BitstreamCursor Stream;
StringRef Strtab;
/// In version 2 of the bitcode we store names of global values and comdats in
/// a string table rather than in the VST.
bool UseStrtab = false;
Expected<unsigned> parseVersionRecord(ArrayRef<uint64_t> Record);
/// If this module uses a string table, pop the reference to the string table
/// and return the referenced string and the rest of the record. Otherwise
/// just return the record itself.
std::pair<StringRef, ArrayRef<uint64_t>>
readNameFromStrtab(ArrayRef<uint64_t> Record);
bool readBlockInfo();
// Contains an arbitrary and optional string identifying the bitcode producer
@ -402,11 +414,22 @@ BitcodeReaderBase::parseVersionRecord(ArrayRef<uint64_t> Record) {
if (Record.size() < 1)
return error("Invalid record");
unsigned ModuleVersion = Record[0];
if (ModuleVersion > 1)
if (ModuleVersion > 2)
return error("Invalid value");
UseStrtab = ModuleVersion >= 2;
return ModuleVersion;
}
std::pair<StringRef, ArrayRef<uint64_t>>
BitcodeReaderBase::readNameFromStrtab(ArrayRef<uint64_t> Record) {
if (!UseStrtab)
return {"", Record};
// Invalid reference. Let the caller complain about the record being empty.
if (Record[0] + Record[1] > Strtab.size())
return {"", {}};
return {StringRef(Strtab.data() + Record[0], Record[1]), Record.slice(2)};
}
class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
LLVMContext &Context;
Module *TheModule = nullptr;
@ -492,8 +515,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
std::vector<std::string> BundleTags;
public:
BitcodeReader(BitstreamCursor Stream, StringRef ProducerIdentification,
LLVMContext &Context);
BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
StringRef ProducerIdentification, LLVMContext &Context);
Error materializeForwardReferencedFunctions();
@ -628,7 +651,10 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
Expected<Value *> recordValue(SmallVectorImpl<uint64_t> &Record,
unsigned NameIndex, Triple &TT);
void setDeferredFunctionInfo(unsigned FuncBitcodeOffsetDelta, Function *F,
ArrayRef<uint64_t> Record);
Error parseValueSymbolTable(uint64_t Offset = 0);
Error parseGlobalValueSymbolTable();
Error parseConstants();
Error rememberAndSkipFunctionBodies();
Error rememberAndSkipFunctionBody();
@ -681,12 +707,15 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
std::string SourceFileName;
public:
ModuleSummaryIndexBitcodeReader(
BitstreamCursor Stream, ModuleSummaryIndex &TheIndex);
ModuleSummaryIndexBitcodeReader(BitstreamCursor Stream, StringRef Strtab,
ModuleSummaryIndex &TheIndex);
Error parseModule(StringRef ModulePath);
private:
void setValueGUID(uint64_t ValueID, StringRef ValueName,
GlobalValue::LinkageTypes Linkage,
StringRef SourceFileName);
Error parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap);
@ -716,10 +745,10 @@ std::error_code llvm::errorToErrorCodeAndEmitErrors(LLVMContext &Ctx,
return std::error_code();
}
BitcodeReader::BitcodeReader(BitstreamCursor Stream,
BitcodeReader::BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
StringRef ProducerIdentification,
LLVMContext &Context)
: BitcodeReaderBase(std::move(Stream)), Context(Context),
: BitcodeReaderBase(std::move(Stream), Strtab), Context(Context),
ValueList(Context) {
this->ProducerIdentification = ProducerIdentification;
}
@ -1749,6 +1778,54 @@ static uint64_t jumpToValueSymbolTable(uint64_t Offset,
return CurrentBit;
}
void BitcodeReader::setDeferredFunctionInfo(unsigned FuncBitcodeOffsetDelta,
Function *F,
ArrayRef<uint64_t> Record) {
// Note that we subtract 1 here because the offset is relative to one word
// before the start of the identification or module block, which was
// historically always the start of the regular bitcode header.
uint64_t FuncWordOffset = Record[1] - 1;
uint64_t FuncBitOffset = FuncWordOffset * 32;
DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;
// Set the LastFunctionBlockBit to point to the last function block.
// Later when parsing is resumed after function materialization,
// we can simply skip that last function block.
if (FuncBitOffset > LastFunctionBlockBit)
LastFunctionBlockBit = FuncBitOffset;
}
/// Read a new-style GlobalValue symbol table.
Error BitcodeReader::parseGlobalValueSymbolTable() {
unsigned FuncBitcodeOffsetDelta =
Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
return error("Invalid record");
SmallVector<uint64_t, 64> Record;
while (true) {
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock:
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
return Error::success();
case BitstreamEntry::Record:
break;
}
Record.clear();
switch (Stream.readRecord(Entry.ID, Record)) {
case bitc::VST_CODE_FNENTRY: // [valueid, offset]
setDeferredFunctionInfo(FuncBitcodeOffsetDelta,
cast<Function>(ValueList[Record[0]]), Record);
break;
}
}
}
/// Parse the value symbol table at either the current parsing location or
/// at the given bit offset if provided.
Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
@ -1756,8 +1833,18 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
// Pass in the Offset to distinguish between calling for the module-level
// VST (where we want to jump to the VST offset) and the function-level
// VST (where we don't).
if (Offset > 0)
if (Offset > 0) {
CurrentBit = jumpToValueSymbolTable(Offset, Stream);
// If this module uses a string table, read this as a module-level VST.
if (UseStrtab) {
if (Error Err = parseGlobalValueSymbolTable())
return Err;
Stream.JumpToBit(CurrentBit);
return Error::success();
}
// Otherwise, the VST will be in a similar format to a function-level VST,
// and will contain symbol names.
}
// Compute the delta between the bitcode indices in the VST (the word offset
// to the word-aligned ENTER_SUBBLOCK for the function block, and that
@ -1818,23 +1905,10 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
return Err;
Value *V = ValOrErr.get();
auto *F = dyn_cast<Function>(V);
// Ignore function offsets emitted for aliases of functions in older
// versions of LLVM.
if (!F)
break;
// Note that we subtract 1 here because the offset is relative to one word
// before the start of the identification or module block, which was
// historically always the start of the regular bitcode header.
uint64_t FuncWordOffset = Record[1] - 1;
uint64_t FuncBitOffset = FuncWordOffset * 32;
DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;
// Set the LastFunctionBlockBit to point to the last function block.
// Later when parsing is resumed after function materialization,
// we can simply skip that last function block.
if (FuncBitOffset > LastFunctionBlockBit)
LastFunctionBlockBit = FuncBitOffset;
if (auto *F = dyn_cast<Function>(V))
setDeferredFunctionInfo(FuncBitcodeOffsetDelta, F, Record);
break;
}
case bitc::VST_CODE_BBENTRY: {
@ -2557,6 +2631,7 @@ Error BitcodeReader::globalCleanup() {
// Look for intrinsic functions which need to be upgraded at some point
for (Function &F : *TheModule) {
MDLoader->upgradeDebugIntrinsics(F);
Function *NewFn;
if (UpgradeIntrinsicFunction(&F, NewFn))
UpgradedIntrinsics[&F] = NewFn;
@ -2626,15 +2701,24 @@ bool BitcodeReaderBase::readBlockInfo() {
}
Error BitcodeReader::parseComdatRecord(ArrayRef<uint64_t> Record) {
// [selection_kind, name]
if (Record.size() < 2)
// v1: [selection_kind, name]
// v2: [strtab_offset, strtab_size, selection_kind]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
if (Record.size() < 1)
return error("Invalid record");
Comdat::SelectionKind SK = getDecodedComdatSelectionKind(Record[0]);
std::string Name;
unsigned ComdatNameSize = Record[1];
Name.reserve(ComdatNameSize);
for (unsigned i = 0; i != ComdatNameSize; ++i)
Name += (char)Record[2 + i];
std::string OldFormatName;
if (!UseStrtab) {
if (Record.size() < 2)
return error("Invalid record");
unsigned ComdatNameSize = Record[1];
OldFormatName.reserve(ComdatNameSize);
for (unsigned i = 0; i != ComdatNameSize; ++i)
OldFormatName += (char)Record[2 + i];
Name = OldFormatName;
}
Comdat *C = TheModule->getOrInsertComdat(Name);
C->setSelectionKind(SK);
ComdatList.push_back(C);
@ -2642,9 +2726,13 @@ Error BitcodeReader::parseComdatRecord(ArrayRef<uint64_t> Record) {
}
Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
// [pointer type, isconst, initid, linkage, alignment, section,
// v1: [pointer type, isconst, initid, linkage, alignment, section,
// visibility, threadlocal, unnamed_addr, externally_initialized,
// dllstorageclass, comdat]
// dllstorageclass, comdat] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
if (Record.size() < 6)
return error("Invalid record");
Type *Ty = getTypeByID(Record[0]);
@ -2692,7 +2780,7 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
ExternallyInitialized = Record[9];
GlobalVariable *NewGV =
new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, "",
new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, Name,
nullptr, TLM, AddressSpace, ExternallyInitialized);
NewGV->setAlignment(Alignment);
if (!Section.empty())
@ -2724,9 +2812,13 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
}
Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
// [type, callingconv, isproto, linkage, paramattr, alignment, section,
// v1: [type, callingconv, isproto, linkage, paramattr, alignment, section,
// visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat,
// prefixdata]
// prefixdata] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
if (Record.size() < 8)
return error("Invalid record");
Type *Ty = getTypeByID(Record[0]);
@ -2742,7 +2834,7 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
return error("Invalid calling convention ID");
Function *Func =
Function::Create(FTy, GlobalValue::ExternalLinkage, "", TheModule);
Function::Create(FTy, GlobalValue::ExternalLinkage, Name, TheModule);
Func->setCallingConv(CC);
bool isProto = Record[2];
@ -2810,11 +2902,15 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
Error BitcodeReader::parseGlobalIndirectSymbolRecord(
unsigned BitCode, ArrayRef<uint64_t> Record) {
// ALIAS_OLD: [alias type, aliasee val#, linkage]
// ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
// dllstorageclass]
// IFUNC: [alias type, addrspace, aliasee val#, linkage,
// visibility, dllstorageclass]
// v1 ALIAS_OLD: [alias type, aliasee val#, linkage] (name in VST)
// v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
// dllstorageclass] (name in VST)
// v1 IFUNC: [alias type, addrspace, aliasee val#, linkage,
// visibility, dllstorageclass] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
bool NewRecord = BitCode != bitc::MODULE_CODE_ALIAS_OLD;
if (Record.size() < (3 + (unsigned)NewRecord))
return error("Invalid record");
@ -2839,10 +2935,10 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord(
GlobalIndirectSymbol *NewGA;
if (BitCode == bitc::MODULE_CODE_ALIAS ||
BitCode == bitc::MODULE_CODE_ALIAS_OLD)
NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage), "",
NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name,
TheModule);
else
NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage), "",
NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name,
nullptr, TheModule);
// Old bitcode files didn't have visibility field.
// Local linkage must have default visibility.
@ -4570,8 +4666,8 @@ std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
}
ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
BitstreamCursor Cursor, ModuleSummaryIndex &TheIndex)
: BitcodeReaderBase(std::move(Cursor)), TheIndex(TheIndex) {}
BitstreamCursor Cursor, StringRef Strtab, ModuleSummaryIndex &TheIndex)
: BitcodeReaderBase(std::move(Cursor), Strtab), TheIndex(TheIndex) {}
std::pair<GlobalValue::GUID, GlobalValue::GUID>
ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
@ -4580,12 +4676,32 @@ ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
return VGI->second;
}
void ModuleSummaryIndexBitcodeReader::setValueGUID(
uint64_t ValueID, StringRef ValueName, GlobalValue::LinkageTypes Linkage,
StringRef SourceFileName) {
std::string GlobalId =
GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName);
auto ValueGUID = GlobalValue::getGUID(GlobalId);
auto OriginalNameID = ValueGUID;
if (GlobalValue::isLocalLinkage(Linkage))
OriginalNameID = GlobalValue::getGUID(ValueName);
if (PrintSummaryGUIDs)
dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
<< ValueName << "\n";
ValueIdToCallGraphGUIDMap[ValueID] =
std::make_pair(ValueGUID, OriginalNameID);
}
// Specialized value symbol table parser used when reading module index
// blocks where we don't actually create global values. The parsed information
// is saved in the bitcode reader for use when later parsing summaries.
Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap) {
// With a strtab the VST is not required to parse the summary.
if (UseStrtab)
return Error::success();
assert(Offset > 0 && "Expected non-zero VST offset");
uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream);
@ -4627,17 +4743,7 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
assert(VLI != ValueIdToLinkageMap.end() &&
"No linkage found for VST entry?");
auto Linkage = VLI->second;
std::string GlobalId =
GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName);
auto ValueGUID = GlobalValue::getGUID(GlobalId);
auto OriginalNameID = ValueGUID;
if (GlobalValue::isLocalLinkage(Linkage))
OriginalNameID = GlobalValue::getGUID(ValueName);
if (PrintSummaryGUIDs)
dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
<< ValueName << "\n";
ValueIdToCallGraphGUIDMap[ValueID] =
std::make_pair(ValueGUID, OriginalNameID);
setValueGUID(ValueID, ValueName, Linkage, SourceFileName);
ValueName.clear();
break;
}
@ -4651,18 +4757,7 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
assert(VLI != ValueIdToLinkageMap.end() &&
"No linkage found for VST entry?");
auto Linkage = VLI->second;
std::string FunctionGlobalId = GlobalValue::getGlobalIdentifier(
ValueName, VLI->second, SourceFileName);
auto FunctionGUID = GlobalValue::getGUID(FunctionGlobalId);
auto OriginalNameID = FunctionGUID;
if (GlobalValue::isLocalLinkage(Linkage))
OriginalNameID = GlobalValue::getGUID(ValueName);
if (PrintSummaryGUIDs)
dbgs() << "GUID " << FunctionGUID << "(" << OriginalNameID << ") is "
<< ValueName << "\n";
ValueIdToCallGraphGUIDMap[ValueID] =
std::make_pair(FunctionGUID, OriginalNameID);
setValueGUID(ValueID, ValueName, Linkage, SourceFileName);
ValueName.clear();
break;
}
@ -4749,6 +4844,11 @@ Error ModuleSummaryIndexBitcodeReader::parseModule(StringRef ModulePath) {
switch (BitCode) {
default:
break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_VERSION: {
if (Error Err = parseVersionRecord(Record).takeError())
return Err;
break;
}
/// MODULE_CODE_SOURCE_FILENAME: [namechar x N]
case bitc::MODULE_CODE_SOURCE_FILENAME: {
SmallString<128> ValueName;
@ -4783,17 +4883,26 @@ Error ModuleSummaryIndexBitcodeReader::parseModule(StringRef ModulePath) {
// was historically always the start of the regular bitcode header.
VSTOffset = Record[0] - 1;
break;
// GLOBALVAR: [pointer type, isconst, initid, linkage, ...]
// FUNCTION: [type, callingconv, isproto, linkage, ...]
// ALIAS: [alias type, addrspace, aliasee val#, linkage, ...]
// v1 GLOBALVAR: [pointer type, isconst, initid, linkage, ...]
// v1 FUNCTION: [type, callingconv, isproto, linkage, ...]
// v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, ...]
// v2: [strtab offset, strtab size, v1]
case bitc::MODULE_CODE_GLOBALVAR:
case bitc::MODULE_CODE_FUNCTION:
case bitc::MODULE_CODE_ALIAS: {
if (Record.size() <= 3)
StringRef Name;
ArrayRef<uint64_t> GVRecord;
std::tie(Name, GVRecord) = readNameFromStrtab(Record);
if (GVRecord.size() <= 3)
return error("Invalid record");
uint64_t RawLinkage = Record[3];
uint64_t RawLinkage = GVRecord[3];
GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
ValueIdToLinkageMap[ValueId++] = Linkage;
if (!UseStrtab) {
ValueIdToLinkageMap[ValueId++] = Linkage;
break;
}
setValueGUID(ValueId++, Name, Linkage, SourceFileName);
break;
}
}
@ -4904,6 +5013,12 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
switch (BitCode) {
default: // Default behavior: ignore.
break;
case bitc::FS_VALUE_GUID: { // [valueid, refguid]
uint64_t ValueID = Record[0];
GlobalValue::GUID RefGUID = Record[1];
ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(RefGUID, RefGUID);
break;
}
// FS_PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid,
// n x (valueid)]
// FS_PERMODULE_PROFILE: [valueid, flags, instcount, numrefs,
@ -5208,6 +5323,35 @@ const std::error_category &llvm::BitcodeErrorCategory() {
return *ErrorCategory;
}
static Expected<StringRef> readStrtab(BitstreamCursor &Stream) {
if (Stream.EnterSubBlock(bitc::STRTAB_BLOCK_ID))
return error("Invalid record");
StringRef Strtab;
while (1) {
BitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
return Strtab;
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::SubBlock:
if (Stream.SkipBlock())
return error("Malformed block");
break;
case BitstreamEntry::Record:
StringRef Blob;
SmallVector<uint64_t, 1> Record;
if (Stream.readRecord(Entry.ID, Record, &Blob) == bitc::STRTAB_BLOB)
Strtab = Blob;
break;
}
}
}
//===----------------------------------------------------------------------===//
// External interface
//===----------------------------------------------------------------------===//
@ -5260,6 +5404,22 @@ llvm::getBitcodeModuleList(MemoryBufferRef Buffer) {
continue;
}
if (Entry.ID == bitc::STRTAB_BLOCK_ID) {
Expected<StringRef> Strtab = readStrtab(Stream);
if (!Strtab)
return Strtab.takeError();
// This string table is used by every preceding bitcode module that does
// not have its own string table. A bitcode file may have multiple
// string tables if it was created by binary concatenation, for example
// with "llvm-cat -b".
for (auto I = Modules.rbegin(), E = Modules.rend(); I != E; ++I) {
if (!I->Strtab.empty())
break;
I->Strtab = *Strtab;
}
continue;
}
if (Stream.SkipBlock())
return error("Malformed block");
continue;
@ -5296,8 +5456,8 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll,
}
Stream.JumpToBit(ModuleBit);
auto *R =
new BitcodeReader(std::move(Stream), ProducerIdentification, Context);
auto *R = new BitcodeReader(std::move(Stream), Strtab, ProducerIdentification,
Context);
std::unique_ptr<Module> M =
llvm::make_unique<Module>(ModuleIdentifier, Context);
@ -5332,7 +5492,7 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
Stream.JumpToBit(ModuleBit);
auto Index = llvm::make_unique<ModuleSummaryIndex>();
ModuleSummaryIndexBitcodeReader R(std::move(Stream), *Index);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index);
if (Error Err = R.parseModule(ModuleIdentifier))
return std::move(Err);

View File

@ -54,6 +54,7 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
@ -452,6 +453,7 @@ class MetadataLoader::MetadataLoaderImpl {
bool StripTBAA = false;
bool HasSeenOldLoopTags = false;
bool NeedUpgradeToDIGlobalVariableExpression = false;
bool NeedDeclareExpressionUpgrade = false;
/// True if metadata is being parsed for a module being ThinLTO imported.
bool IsImporting = false;
@ -511,6 +513,26 @@ class MetadataLoader::MetadataLoaderImpl {
}
}
/// Remove a leading DW_OP_deref from DIExpressions in a dbg.declare that
/// describes a function argument.
void upgradeDeclareExpressions(Function &F) {
if (!NeedDeclareExpressionUpgrade)
return;
for (auto &BB : F)
for (auto &I : BB)
if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
if (auto *DIExpr = DDI->getExpression())
if (DIExpr->startsWithDeref() &&
dyn_cast_or_null<Argument>(DDI->getAddress())) {
SmallVector<uint64_t, 8> Ops;
Ops.append(std::next(DIExpr->elements_begin()),
DIExpr->elements_end());
auto *E = DIExpression::get(Context, Ops);
DDI->setOperand(2, MetadataAsValue::get(Context, E));
}
}
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
@ -565,6 +587,7 @@ class MetadataLoader::MetadataLoaderImpl {
unsigned size() const { return MetadataList.size(); }
void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); }
void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
};
static Error error(const Twine &Message) {
@ -1520,12 +1543,32 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
return error("Invalid record");
IsDistinct = Record[0] & 1;
bool HasOpFragment = Record[0] & 2;
uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
if (!HasOpFragment)
if (unsigned N = Elts.size())
if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
unsigned N = Elts.size();
// Perform various upgrades.
switch (Version) {
case 0:
if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
LLVM_FALLTHROUGH;
case 1:
// Move DW_OP_deref to the end.
if (N && Elts[0] == dwarf::DW_OP_deref) {
auto End = Elts.end();
if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
End = std::prev(End, 3);
std::move(std::next(Elts.begin()), End, Elts.begin());
*std::prev(End) = dwarf::DW_OP_deref;
}
NeedDeclareExpressionUpgrade = true;
LLVM_FALLTHROUGH;
case 2:
// Up-to-date!
break;
default:
return error("Invalid record");
}
MetadataList.assignValue(
GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))),
@ -1858,3 +1901,7 @@ bool MetadataLoader::isStrippingTBAA() { return Pimpl->isStrippingTBAA(); }
unsigned MetadataLoader::size() const { return Pimpl->size(); }
void MetadataLoader::shrinkTo(unsigned N) { return Pimpl->shrinkTo(N); }
void MetadataLoader::upgradeDebugIntrinsics(Function &F) {
return Pimpl->upgradeDebugIntrinsics(F);
}

View File

@ -79,6 +79,9 @@ class MetadataLoader {
unsigned size() const;
void shrinkTo(unsigned N);
/// Perform bitcode upgrades on llvm.dbg.* calls.
void upgradeDebugIntrinsics(Function &F);
};
}

View File

@ -28,6 +28,7 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/UseListOrder.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Program.h"
@ -76,26 +77,28 @@ class BitcodeWriterBase {
/// The stream created and owned by the client.
BitstreamWriter &Stream;
/// Saves the offset of the VSTOffset record that must eventually be
/// backpatched with the offset of the actual VST.
uint64_t VSTOffsetPlaceholder = 0;
public:
/// Constructs a BitcodeWriterBase object that writes to the provided
/// \p Stream.
BitcodeWriterBase(BitstreamWriter &Stream) : Stream(Stream) {}
protected:
bool hasVSTOffsetPlaceholder() { return VSTOffsetPlaceholder != 0; }
void writeValueSymbolTableForwardDecl();
void writeBitcodeHeader();
void writeModuleVersion();
};
void BitcodeWriterBase::writeModuleVersion() {
// VERSION: [version#]
Stream.EmitRecord(bitc::MODULE_CODE_VERSION, ArrayRef<uint64_t>{2});
}
/// Class to manage the bitcode writing for a module.
class ModuleBitcodeWriter : public BitcodeWriterBase {
/// Pointer to the buffer allocated by caller for bitcode writing.
const SmallVectorImpl<char> &Buffer;
StringTableBuilder &StrtabBuilder;
/// The Module to write to bitcode.
const Module &M;
@ -127,15 +130,20 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
/// Tracks the last value id recorded in the GUIDToValueMap.
unsigned GlobalValueId;
/// Saves the offset of the VSTOffset record that must eventually be
/// backpatched with the offset of the actual VST.
uint64_t VSTOffsetPlaceholder = 0;
public:
/// Constructs a ModuleBitcodeWriter object for the given Module,
/// writing to the provided \p Buffer.
ModuleBitcodeWriter(const Module *M, SmallVectorImpl<char> &Buffer,
StringTableBuilder &StrtabBuilder,
BitstreamWriter &Stream, bool ShouldPreserveUseListOrder,
const ModuleSummaryIndex *Index, bool GenerateHash,
ModuleHash *ModHash = nullptr)
: BitcodeWriterBase(Stream), Buffer(Buffer), M(*M),
VE(*M, ShouldPreserveUseListOrder), Index(Index),
: BitcodeWriterBase(Stream), Buffer(Buffer), StrtabBuilder(StrtabBuilder),
M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index),
GenerateHash(GenerateHash), ModHash(ModHash),
BitcodeStartBit(Stream.GetCurrentBitNo()) {
// Assign ValueIds to any callee values in the index that came from
@ -169,6 +177,7 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
void writeAttributeTable();
void writeTypeTable();
void writeComdats();
void writeValueSymbolTableForwardDecl();
void writeModuleInfo();
void writeValueAsMetadata(const ValueAsMetadata *MD,
SmallVectorImpl<uint64_t> &Record);
@ -261,9 +270,9 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
SmallVectorImpl<uint64_t> &Vals);
void writeInstruction(const Instruction &I, unsigned InstID,
SmallVectorImpl<unsigned> &Vals);
void writeValueSymbolTable(
const ValueSymbolTable &VST, bool IsModuleLevel = false,
DenseMap<const Function *, uint64_t> *FunctionToBitcodeIndex = nullptr);
void writeFunctionLevelValueSymbolTable(const ValueSymbolTable &VST);
void writeGlobalValueSymbolTable(
DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex);
void writeUseList(UseListOrder &&Order);
void writeUseListBlock(const Function *F);
void
@ -477,7 +486,6 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
private:
void writeModStrings();
void writeCombinedValueSymbolTable();
void writeCombinedGlobalValueSummary();
/// Indicates whether the provided \p ModulePath should be written into
@ -492,15 +500,15 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
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) {
const auto &VMI = GUIDToValueIdMap.find(ValGUID);
// If this GUID doesn't have an entry, assign one.
if (VMI == GUIDToValueIdMap.end()) {
GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
return GlobalValueId;
} else {
return VMI->second;
}
auto VMI = GUIDToValueIdMap.find(ValGUID);
assert(VMI != GUIDToValueIdMap.end());
return VMI->second;
}
std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; }
};
@ -1047,13 +1055,10 @@ static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) {
void ModuleBitcodeWriter::writeComdats() {
SmallVector<unsigned, 64> Vals;
for (const Comdat *C : VE.getComdats()) {
// COMDAT: [selection_kind, name]
// COMDAT: [strtab offset, strtab size, selection_kind]
Vals.push_back(StrtabBuilder.add(C->getName()));
Vals.push_back(C->getName().size());
Vals.push_back(getEncodedComdatSelectionKind(*C));
size_t Size = C->getName().size();
assert(isUInt<32>(Size));
Vals.push_back(Size);
for (char Chr : C->getName())
Vals.push_back((unsigned char)Chr);
Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0);
Vals.clear();
}
@ -1062,7 +1067,7 @@ void ModuleBitcodeWriter::writeComdats() {
/// Write a record that will eventually hold the word offset of the
/// module-level VST. For now the offset is 0, which will be backpatched
/// after the real VST is written. Saves the bit offset to backpatch.
void BitcodeWriterBase::writeValueSymbolTableForwardDecl() {
void ModuleBitcodeWriter::writeValueSymbolTableForwardDecl() {
// Write a placeholder value in for the offset of the real VST,
// which is written after the function blocks so that it can include
// the offset of each function. The placeholder offset will be
@ -1165,6 +1170,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Add an abbrev for common globals with no visibility or thread localness.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(MaxGlobalType+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddrSpace << 2
@ -1188,15 +1195,42 @@ void ModuleBitcodeWriter::writeModuleInfo() {
SimpleGVarAbbrev = Stream.EmitAbbrev(std::move(Abbv));
}
// Emit the global variable information.
SmallVector<unsigned, 64> Vals;
// Emit the module's source file name.
{
StringEncoding Bits = getStringEncoding(M.getSourceFileName().data(),
M.getSourceFileName().size());
BitCodeAbbrevOp AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8);
if (Bits == SE_Char6)
AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Char6);
else if (Bits == SE_Fixed7)
AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7);
// MODULE_CODE_SOURCE_FILENAME: [namechar x N]
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_SOURCE_FILENAME));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(AbbrevOpToUse);
unsigned FilenameAbbrev = Stream.EmitAbbrev(std::move(Abbv));
for (const auto P : M.getSourceFileName())
Vals.push_back((unsigned char)P);
// Emit the finished record.
Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev);
Vals.clear();
}
// Emit the global variable information.
for (const GlobalVariable &GV : M.globals()) {
unsigned AbbrevToUse = 0;
// GLOBALVAR: [type, isconst, initid,
// GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal,
// unnamed_addr, externally_initialized, dllstorageclass,
// comdat]
Vals.push_back(StrtabBuilder.add(GV.getName()));
Vals.push_back(GV.getName().size());
Vals.push_back(VE.getTypeID(GV.getValueType()));
Vals.push_back(GV.getType()->getAddressSpace() << 2 | 2 | GV.isConstant());
Vals.push_back(GV.isDeclaration() ? 0 :
@ -1226,9 +1260,12 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the function proto information.
for (const Function &F : M) {
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
// section, visibility, gc, unnamed_addr, prologuedata,
// dllstorageclass, comdat, prefixdata, personalityfn]
// FUNCTION: [strtab offset, strtab size, type, callingconv, isproto,
// linkage, paramattrs, alignment, section, visibility, gc,
// unnamed_addr, prologuedata, dllstorageclass, comdat,
// prefixdata, personalityfn]
Vals.push_back(StrtabBuilder.add(F.getName()));
Vals.push_back(F.getName().size());
Vals.push_back(VE.getTypeID(F.getFunctionType()));
Vals.push_back(F.getCallingConv());
Vals.push_back(F.isDeclaration());
@ -1255,8 +1292,10 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the alias information.
for (const GlobalAlias &A : M.aliases()) {
// ALIAS: [alias type, aliasee val#, linkage, visibility, dllstorageclass,
// threadlocal, unnamed_addr]
// ALIAS: [strtab offset, strtab size, alias type, aliasee val#, linkage,
// visibility, dllstorageclass, threadlocal, unnamed_addr]
Vals.push_back(StrtabBuilder.add(A.getName()));
Vals.push_back(A.getName().size());
Vals.push_back(VE.getTypeID(A.getValueType()));
Vals.push_back(A.getType()->getAddressSpace());
Vals.push_back(VE.getValueID(A.getAliasee()));
@ -1272,7 +1311,10 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the ifunc information.
for (const GlobalIFunc &I : M.ifuncs()) {
// IFUNC: [ifunc type, address space, resolver val#, linkage, visibility]
// IFUNC: [strtab offset, strtab size, ifunc type, address space, resolver
// val#, linkage, visibility]
Vals.push_back(StrtabBuilder.add(I.getName()));
Vals.push_back(I.getName().size());
Vals.push_back(VE.getTypeID(I.getValueType()));
Vals.push_back(I.getType()->getAddressSpace());
Vals.push_back(VE.getValueID(I.getResolver()));
@ -1282,34 +1324,6 @@ void ModuleBitcodeWriter::writeModuleInfo() {
Vals.clear();
}
// Emit the module's source file name.
{
StringEncoding Bits = getStringEncoding(M.getSourceFileName().data(),
M.getSourceFileName().size());
BitCodeAbbrevOp AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8);
if (Bits == SE_Char6)
AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Char6);
else if (Bits == SE_Fixed7)
AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7);
// MODULE_CODE_SOURCE_FILENAME: [namechar x N]
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_SOURCE_FILENAME));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(AbbrevOpToUse);
unsigned FilenameAbbrev = Stream.EmitAbbrev(std::move(Abbv));
for (const auto P : M.getSourceFileName())
Vals.push_back((unsigned char)P);
// Emit the finished record.
Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev);
Vals.clear();
}
// If we have a VST, write the VSTOFFSET record placeholder.
if (M.getValueSymbolTable().empty())
return;
writeValueSymbolTableForwardDecl();
}
@ -1757,9 +1771,8 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
const uint64_t HasOpFragmentFlag = 1 << 1;
Record.push_back((uint64_t)N->isDistinct() | HasOpFragmentFlag);
const uint64_t Version = 2 << 1;
Record.push_back((uint64_t)N->isDistinct() | Version);
Record.append(N->elements_begin(), N->elements_end());
Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
@ -2839,78 +2852,60 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Vals.clear();
}
/// Emit names for globals/functions etc. \p IsModuleLevel is true when
/// we are writing the module-level VST, where we are including a function
/// bitcode index and need to backpatch the VST forward declaration record.
void ModuleBitcodeWriter::writeValueSymbolTable(
const ValueSymbolTable &VST, bool IsModuleLevel,
DenseMap<const Function *, uint64_t> *FunctionToBitcodeIndex) {
if (VST.empty()) {
// writeValueSymbolTableForwardDecl should have returned early as
// well. Ensure this handling remains in sync by asserting that
// the placeholder offset is not set.
assert(!IsModuleLevel || !hasVSTOffsetPlaceholder());
return;
}
if (IsModuleLevel && hasVSTOffsetPlaceholder()) {
// Get the offset of the VST we are writing, and backpatch it into
// the VST forward declaration record.
uint64_t VSTOffset = Stream.GetCurrentBitNo();
// The BitcodeStartBit was the stream offset of the identification block.
VSTOffset -= bitcodeStartBit();
assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
// Note that we add 1 here because the offset is relative to one word
// before the start of the identification block, which was historically
// always the start of the regular bitcode header.
Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32 + 1);
}
/// Write a GlobalValue VST to the module. The purpose of this data structure is
/// to allow clients to efficiently find the function body.
void ModuleBitcodeWriter::writeGlobalValueSymbolTable(
DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex) {
// Get the offset of the VST we are writing, and backpatch it into
// the VST forward declaration record.
uint64_t VSTOffset = Stream.GetCurrentBitNo();
// The BitcodeStartBit was the stream offset of the identification block.
VSTOffset -= bitcodeStartBit();
assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
// Note that we add 1 here because the offset is relative to one word
// before the start of the identification block, which was historically
// always the start of the regular bitcode header.
Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32 + 1);
Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
// For the module-level VST, add abbrev Ids for the VST_CODE_FNENTRY
// records, which are not used in the per-function VSTs.
unsigned FnEntry8BitAbbrev;
unsigned FnEntry7BitAbbrev;
unsigned FnEntry6BitAbbrev;
unsigned GUIDEntryAbbrev;
if (IsModuleLevel && hasVSTOffsetPlaceholder()) {
// 8-bit fixed-width VST_CODE_FNENTRY function strings.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
FnEntry8BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
unsigned FnEntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
// 7-bit fixed width VST_CODE_FNENTRY function strings.
Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
FnEntry7BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
for (const Function &F : M) {
uint64_t Record[2];
// 6-bit char6 VST_CODE_FNENTRY function strings.
Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
FnEntry6BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
if (F.isDeclaration())
continue;
// FIXME: Change the name of this record as it is now used by
// the per-module index as well.
Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid
GUIDEntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
Record[0] = VE.getValueID(&F);
// Save the word offset of the function (from the start of the
// actual bitcode written to the stream).
uint64_t BitcodeIndex = FunctionToBitcodeIndex[&F] - bitcodeStartBit();
assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");
// Note that we add 1 here because the offset is relative to one word
// before the start of the identification block, which was historically
// always the start of the regular bitcode header.
Record[1] = BitcodeIndex / 32 + 1;
Stream.EmitRecord(bitc::VST_CODE_FNENTRY, Record, FnEntryAbbrev);
}
Stream.ExitBlock();
}
/// Emit names for arguments, instructions and basic blocks in a function.
void ModuleBitcodeWriter::writeFunctionLevelValueSymbolTable(
const ValueSymbolTable &VST) {
if (VST.empty())
return;
Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
// FIXME: Set up the abbrev, we know how many values there are!
// FIXME: We know if the type names can use 7-bit ascii.
SmallVector<uint64_t, 64> NameVals;
@ -2923,38 +2918,13 @@ void ModuleBitcodeWriter::writeValueSymbolTable(
unsigned AbbrevToUse = VST_ENTRY_8_ABBREV;
NameVals.push_back(VE.getValueID(Name.getValue()));
Function *F = dyn_cast<Function>(Name.getValue());
// VST_CODE_ENTRY: [valueid, namechar x N]
// VST_CODE_FNENTRY: [valueid, funcoffset, namechar x N]
// VST_CODE_BBENTRY: [bbid, namechar x N]
unsigned Code;
if (isa<BasicBlock>(Name.getValue())) {
Code = bitc::VST_CODE_BBENTRY;
if (Bits == SE_Char6)
AbbrevToUse = VST_BBENTRY_6_ABBREV;
} else if (F && !F->isDeclaration()) {
// Must be the module-level VST, where we pass in the Index and
// have a VSTOffsetPlaceholder. The function-level VST should not
// contain any Function symbols.
assert(FunctionToBitcodeIndex);
assert(hasVSTOffsetPlaceholder());
// Save the word offset of the function (from the start of the
// actual bitcode written to the stream).
uint64_t BitcodeIndex = (*FunctionToBitcodeIndex)[F] - bitcodeStartBit();
assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");
// Note that we add 1 here because the offset is relative to one word
// before the start of the identification block, which was historically
// always the start of the regular bitcode header.
NameVals.push_back(BitcodeIndex / 32 + 1);
Code = bitc::VST_CODE_FNENTRY;
AbbrevToUse = FnEntry8BitAbbrev;
if (Bits == SE_Char6)
AbbrevToUse = FnEntry6BitAbbrev;
else if (Bits == SE_Fixed7)
AbbrevToUse = FnEntry7BitAbbrev;
} else {
Code = bitc::VST_CODE_ENTRY;
if (Bits == SE_Char6)
@ -2970,47 +2940,7 @@ void ModuleBitcodeWriter::writeValueSymbolTable(
Stream.EmitRecord(Code, NameVals, AbbrevToUse);
NameVals.clear();
}
// Emit any GUID valueIDs created for indirect call edges into the
// module-level VST.
if (IsModuleLevel && hasVSTOffsetPlaceholder())
for (const auto &GI : valueIds()) {
NameVals.push_back(GI.second);
NameVals.push_back(GI.first);
Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals,
GUIDEntryAbbrev);
NameVals.clear();
}
Stream.ExitBlock();
}
/// Emit function names and summary offsets for the combined index
/// used by ThinLTO.
void IndexBitcodeWriter::writeCombinedValueSymbolTable() {
assert(hasVSTOffsetPlaceholder() && "Expected non-zero VSTOffsetPlaceholder");
// Get the offset of the VST we are writing, and backpatch it into
// the VST forward declaration record.
uint64_t VSTOffset = Stream.GetCurrentBitNo();
assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32);
Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid
unsigned EntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
SmallVector<uint64_t, 64> NameVals;
for (const auto &GVI : valueIds()) {
// VST_CODE_COMBINED_ENTRY: [valueid, refguid]
NameVals.push_back(GVI.second);
NameVals.push_back(GVI.first);
// Emit the finished record.
Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals, EntryAbbrev);
NameVals.clear();
}
Stream.ExitBlock();
}
@ -3114,7 +3044,7 @@ void ModuleBitcodeWriter::writeFunction(
// Emit names for all the instructions etc.
if (auto *Symtab = F.getValueSymbolTable())
writeValueSymbolTable(*Symtab);
writeFunctionLevelValueSymbolTable(*Symtab);
if (NeedsMetadataAttachment)
writeFunctionMetadataAttachment(F);
@ -3502,6 +3432,11 @@ void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() {
return;
}
for (const auto &GVI : valueIds()) {
Stream.EmitRecord(bitc::FS_VALUE_GUID,
ArrayRef<uint64_t>{GVI.second, GVI.first});
}
// Abbrev for FS_PERMODULE.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE));
@ -3594,6 +3529,39 @@ 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.
for (const auto &I : *this) {
if (auto *VS = dyn_cast<GlobalVarSummary>(I.second)) {
for (auto &RI : VS->refs())
assignValueId(RI.getGUID());
continue;
}
auto *FS = dyn_cast<FunctionSummary>(I.second);
if (!FS)
continue;
for (auto &RI : FS->refs())
assignValueId(RI.getGUID());
for (auto &EI : FS->calls()) {
GlobalValue::GUID GUID = EI.first.getGUID();
if (!hasValueId(GUID)) {
// 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))
continue;
}
assignValueId(GUID);
}
}
for (const auto &GVI : valueIds()) {
Stream.EmitRecord(bitc::FS_VALUE_GUID,
ArrayRef<uint64_t>{GVI.second, GVI.first});
}
// Abbrev for FS_COMBINED.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED));
@ -3808,10 +3776,7 @@ void ModuleBitcodeWriter::write() {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
size_t BlockStartPos = Buffer.size();
SmallVector<unsigned, 1> Vals;
unsigned CurVersion = 1;
Vals.push_back(CurVersion);
Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
writeModuleVersion();
// Emit blockinfo, which defines the standard abbreviations etc.
writeBlockInfo();
@ -3857,8 +3822,7 @@ void ModuleBitcodeWriter::write() {
if (Index)
writePerModuleGlobalValueSummary();
writeValueSymbolTable(M.getValueSymbolTable(),
/* IsModuleLevel */ true, &FunctionToBitcodeIndex);
writeGlobalValueSymbolTable(FunctionToBitcodeIndex);
writeModuleHash(BlockStartPos);
@ -3946,13 +3910,45 @@ BitcodeWriter::BitcodeWriter(SmallVectorImpl<char> &Buffer)
writeBitcodeHeader(*Stream);
}
BitcodeWriter::~BitcodeWriter() = default;
BitcodeWriter::~BitcodeWriter() { assert(WroteStrtab); }
void BitcodeWriter::writeBlob(unsigned Block, unsigned Record, StringRef Blob) {
Stream->EnterSubblock(Block, 3);
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(Record));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
auto AbbrevNo = Stream->EmitAbbrev(std::move(Abbv));
Stream->EmitRecordWithBlob(AbbrevNo, ArrayRef<uint64_t>{Record}, Blob);
Stream->ExitBlock();
}
void BitcodeWriter::writeStrtab() {
assert(!WroteStrtab);
std::vector<char> Strtab;
StrtabBuilder.finalizeInOrder();
Strtab.resize(StrtabBuilder.getSize());
StrtabBuilder.write((uint8_t *)Strtab.data());
writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB,
{Strtab.data(), Strtab.size()});
WroteStrtab = true;
}
void BitcodeWriter::copyStrtab(StringRef Strtab) {
writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB, Strtab);
WroteStrtab = true;
}
void BitcodeWriter::writeModule(const Module *M,
bool ShouldPreserveUseListOrder,
const ModuleSummaryIndex *Index,
bool GenerateHash, ModuleHash *ModHash) {
ModuleBitcodeWriter ModuleWriter(M, Buffer, *Stream,
ModuleBitcodeWriter ModuleWriter(M, Buffer, StrtabBuilder, *Stream,
ShouldPreserveUseListOrder, Index,
GenerateHash, ModHash);
ModuleWriter.write();
@ -3976,6 +3972,7 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
BitcodeWriter Writer(Buffer);
Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash,
ModHash);
Writer.writeStrtab();
if (TT.isOSDarwin() || TT.isOSBinFormatMachO())
emitDarwinBCHeaderAndTrailer(Buffer, TT);
@ -3987,13 +3984,7 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
void IndexBitcodeWriter::write() {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
SmallVector<unsigned, 1> Vals;
unsigned CurVersion = 1;
Vals.push_back(CurVersion);
Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
// If we have a VST, write the VSTOFFSET record placeholder.
writeValueSymbolTableForwardDecl();
writeModuleVersion();
// Write the module paths in the combined index.
writeModStrings();
@ -4001,10 +3992,6 @@ void IndexBitcodeWriter::write() {
// Write the summary combined index records.
writeCombinedGlobalValueSummary();
// Need a special VST writer for the combined index (we don't have a
// real VST and real values when this is invoked).
writeCombinedValueSymbolTable();
Stream.ExitBlock();
}

View File

@ -834,9 +834,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << " <- ";
// The second operand is only an offset if it's an immediate.
bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0;
bool Deref = false;
bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0;
for (unsigned i = 0; i < Expr->getNumElements(); ++i) {
uint64_t Op = Expr->getElement(i);
if (Op == dwarf::DW_OP_LLVM_fragment) {
@ -844,7 +844,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
break;
} else if (Deref) {
// We currently don't support extra Offsets or derefs after the first
// one. Bail out early instead of emitting an incorrect comment
// one. Bail out early instead of emitting an incorrect comment.
OS << " [complex expression]";
AP.OutStreamer->emitRawComment(OS.str());
return true;
@ -899,12 +899,12 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
AP.OutStreamer->emitRawComment(OS.str());
return true;
}
if (Deref)
if (MemLoc || Deref)
OS << '[';
OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
}
if (Deref)
if (MemLoc || Deref)
OS << '+' << Offset << ']';
// NOTE: Want this comment at start of line, don't emit with AddComment.
@ -1356,7 +1356,7 @@ bool AsmPrinter::doFinalization(Module &M) {
OutContext.getOrCreateSymbol(StringRef("__morestack_addr"));
OutStreamer->EmitLabel(AddrSymbol);
unsigned PtrSize = M.getDataLayout().getPointerSize(0);
unsigned PtrSize = MAI->getCodePointerSize();
OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("__morestack"),
PtrSize);
}
@ -2246,7 +2246,7 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
// chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
ExtraBits = Realigned.getRawData()[0] &
(((uint64_t)-1) >> (64 - ExtraBitsSize));
Realigned = Realigned.lshr(ExtraBitsSize);
Realigned.lshrInPlace(ExtraBitsSize);
} else
ExtraBits = Realigned.getRawData()[BitWidth / 64];
}
@ -2781,7 +2781,7 @@ void AsmPrinter::emitXRayTable() {
// before the function's end, we assume that this is happening after
// the last return instruction.
auto WordSizeBytes = TM.getPointerSize();
auto WordSizeBytes = MAI->getCodePointerSize();
MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
OutStreamer->EmitCodeAlignment(16);
OutStreamer->EmitSymbolValue(Tmp, WordSizeBytes, false);

View File

@ -1136,7 +1136,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
DITypeRef ElementTypeRef = Ty->getBaseType();
TypeIndex ElementTypeIndex = getTypeIndex(ElementTypeRef);
// IndexType is size_t, which depends on the bitness of the target.
TypeIndex IndexType = Asm->MAI->getPointerSize() == 8
TypeIndex IndexType = Asm->TM.getPointerSize() == 8
? TypeIndex(SimpleTypeKind::UInt64Quad)
: TypeIndex(SimpleTypeKind::UInt32Long);
@ -1342,8 +1342,8 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType());
PointerKind PK = Asm->MAI->getPointerSize() == 8 ? PointerKind::Near64
: PointerKind::Near32;
PointerKind PK = Asm->TM.getPointerSize() == 8 ? PointerKind::Near64
: PointerKind::Near32;
bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
: PointerMode::PointerToDataMember;
@ -1458,7 +1458,8 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
}
TypeIndex CodeViewDebug::lowerTypeVFTableShape(const DIDerivedType *Ty) {
unsigned VSlotCount = Ty->getSizeInBits() / (8 * Asm->MAI->getPointerSize());
unsigned VSlotCount =
Ty->getSizeInBits() / (8 * Asm->MAI->getCodePointerSize());
SmallVector<VFTableSlotKind, 4> Slots(VSlotCount, VFTableSlotKind::Near);
VFTableShapeRecord VFTSR(Slots);

View File

@ -31,6 +31,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
//===----------------------------------------------------------------------===//
// DIEAbbrevData Implementation
//===----------------------------------------------------------------------===//
@ -79,15 +81,22 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const {
dwarf::AttributeString(AttrData.getAttribute()).data());
// Emit form type.
#ifndef NDEBUG
// Could be an assertion, but this way we can see the failing form code
// easily, which helps track down where it came from.
if (!dwarf::isValidFormForVersion(AttrData.getForm(),
AP->getDwarfVersion())) {
DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm())
<< " for DWARF version " << AP->getDwarfVersion() << "\n");
llvm_unreachable("Invalid form for specified DWARF version");
}
#endif
AP->EmitULEB128(AttrData.getForm(),
dwarf::FormEncodingString(AttrData.getForm()).data());
// Emit value for DW_FORM_implicit_const.
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) {
assert(AP->getDwarfVersion() >= 5 &&
"DW_FORM_implicit_const is supported starting from DWARFv5");
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
AP->EmitSLEB128(AttrData.getValue());
}
}
// Mark end of abbreviation.
@ -518,7 +527,7 @@ unsigned DIELabel::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
if (Form == dwarf::DW_FORM_sec_offset) return 4;
if (Form == dwarf::DW_FORM_strp) return 4;
return AP->getPointerSize();
return AP->MAI->getCodePointerSize();
}
LLVM_DUMP_METHOD
@ -540,7 +549,7 @@ unsigned DIEDelta::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
if (Form == dwarf::DW_FORM_sec_offset) return 4;
if (Form == dwarf::DW_FORM_strp) return 4;
return AP->getPointerSize();
return AP->MAI->getCodePointerSize();
}
LLVM_DUMP_METHOD
@ -682,7 +691,7 @@ unsigned DIEEntry::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
return getULEB128Size(Entry->getOffset());
case dwarf::DW_FORM_ref_addr:
if (AP->getDwarfVersion() == 2)
return AP->getPointerSize();
return AP->MAI->getCodePointerSize();
switch (AP->OutStreamer->getContext().getDwarfFormat()) {
case dwarf::DWARF32:
return 4;
@ -808,7 +817,7 @@ unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
return 4;
if (Form == dwarf::DW_FORM_sec_offset)
return 4;
return AP->getPointerSize();
return AP->MAI->getCodePointerSize();
}
/// EmitValue - Emit label value.

View File

@ -547,18 +547,19 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto &Fragment : DV.getFrameIndexExprs()) {
unsigned FrameReg = 0;
const DIExpression *Expr = Fragment.Expr;
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
DwarfExpr.addFragmentOffset(Fragment.Expr);
DwarfExpr.addFragmentOffset(Expr);
SmallVector<uint64_t, 8> Ops;
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Offset);
Ops.push_back(dwarf::DW_OP_deref);
Ops.append(Fragment.Expr->elements_begin(), Fragment.Expr->elements_end());
DIExpressionCursor Expr(Ops);
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addMachineRegExpression(
*Asm->MF->getSubtarget().getRegisterInfo(), Expr, FrameReg);
DwarfExpr.addExpression(std::move(Expr));
*Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
DwarfExpr.addExpression(std::move(Cursor));
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
@ -779,12 +780,13 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
if (Location.isIndirect())
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect()) {
if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
Ops.push_back(dwarf::DW_OP_deref);
}
DIExpressionCursor Cursor(Ops);
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
@ -807,12 +809,13 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
const DIExpression *DIExpr = DV.getSingleExpression();
DwarfExpr.addFragmentOffset(DIExpr);
if (Location.isIndirect())
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect()) {
if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
Ops.push_back(dwarf::DW_OP_deref);
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
DIExpressionCursor Cursor(Ops);

View File

@ -1517,13 +1517,12 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DwarfExpr.addUnsignedConstant(Value.getInt());
} else if (Value.isLocation()) {
MachineLocation Location = Value.getLoc();
if (Location.isIndirect())
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 8> Ops;
// FIXME: Should this condition be Location.isIndirect() instead?
if (Location.getOffset()) {
if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
Ops.push_back(dwarf::DW_OP_deref);
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
DIExpressionCursor Cursor(Ops);
@ -1578,7 +1577,7 @@ void DwarfDebug::emitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
unsigned char Size = Asm->MAI->getCodePointerSize();
for (const auto &List : DebugLocs.getLists()) {
Asm->OutStreamer->EmitLabel(List.Label);
const DwarfCompileUnit *CU = List.CU;
@ -1708,7 +1707,7 @@ void DwarfDebug::emitDebugARanges() {
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
unsigned PtrSize = Asm->getDataLayout().getPointerSize();
unsigned PtrSize = Asm->MAI->getCodePointerSize();
// Build a list of CUs used.
std::vector<DwarfCompileUnit *> CUs;
@ -1791,7 +1790,7 @@ void DwarfDebug::emitDebugRanges() {
Asm->getObjFileLowering().getDwarfRangesSection());
// Size for our labels.
unsigned char Size = Asm->getDataLayout().getPointerSize();
unsigned char Size = Asm->MAI->getCodePointerSize();
// Grab the specific ranges for the compile units in the module.
for (const auto &I : CUMap) {

View File

@ -23,9 +23,12 @@
using namespace llvm;
void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
if (DwarfReg < 32) {
emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
assert((LocationKind == Unknown || LocationKind == Register) &&
"location description already locked down");
LocationKind = Register;
if (DwarfReg < 32) {
emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
} else {
emitOp(dwarf::DW_OP_regx, Comment);
emitUnsigned(DwarfReg);
@ -34,6 +37,7 @@ void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
void DwarfExpression::addBReg(int DwarfReg, int Offset) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
assert(LocationKind != Register && "location description already locked down");
if (DwarfReg < 32) {
emitOp(dwarf::DW_OP_breg0 + DwarfReg);
} else {
@ -156,18 +160,23 @@ void DwarfExpression::addStackValue() {
}
void DwarfExpression::addSignedConstant(int64_t Value) {
assert(LocationKind == Implicit || LocationKind == Unknown);
LocationKind = Implicit;
emitOp(dwarf::DW_OP_consts);
emitSigned(Value);
addStackValue();
}
void DwarfExpression::addUnsignedConstant(uint64_t Value) {
assert(LocationKind == Implicit || LocationKind == Unknown);
LocationKind = Implicit;
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Value);
addStackValue();
}
void DwarfExpression::addUnsignedConstant(const APInt &Value) {
assert(LocationKind == Implicit || LocationKind == Unknown);
LocationKind = Implicit;
unsigned Size = Value.getBitWidth();
const uint64_t *Data = Value.getRawData();
@ -178,7 +187,8 @@ void DwarfExpression::addUnsignedConstant(const APInt &Value) {
addUnsignedConstant(*Data++);
if (Offset == 0 && Size <= 64)
break;
addOpPiece(std::min(Size-Offset, 64u), Offset);
addStackValue();
addOpPiece(std::min(Size - Offset, 64u), Offset);
Offset += 64;
}
}
@ -206,7 +216,7 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
}
// Handle simple register locations.
if (!HasComplexExpression) {
if (LocationKind != Memory && !HasComplexExpression) {
for (auto &Reg : DwarfRegs) {
if (Reg.DwarfRegNo >= 0)
addReg(Reg.DwarfRegNo, Reg.Comment);
@ -216,62 +226,65 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return true;
}
// Don't emit locations that cannot be expressed without DW_OP_stack_value.
if (DwarfVersion < 4)
if (std::any_of(ExprCursor.begin(), ExprCursor.end(),
[](DIExpression::ExprOperand Op) -> bool {
return Op.getOp() == dwarf::DW_OP_stack_value;
})) {
DwarfRegs.clear();
return false;
}
assert(DwarfRegs.size() == 1);
auto Reg = DwarfRegs[0];
bool FBReg = isFrameRegister(TRI, MachineReg);
bool FBReg = isFrameRegister(TRI, MachineReg);
int SignedOffset = 0;
assert(Reg.Size == 0 && "subregister has same size as superregister");
// Pattern-match combinations for which more efficient representations exist.
switch (Op->getOp()) {
default: {
if (FBReg)
addFBReg(0);
else
addReg(Reg.DwarfRegNo, 0);
break;
}
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus: {
// [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
// [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset].
auto N = ExprCursor.peekNext();
if (N && N->getOp() == dwarf::DW_OP_deref) {
int Offset = Op->getArg(0);
int SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
if (FBReg)
addFBReg(SignedOffset);
else
addBReg(Reg.DwarfRegNo, SignedOffset);
ExprCursor.consume(2);
break;
}
addReg(Reg.DwarfRegNo, 0);
break;
}
case dwarf::DW_OP_deref:
// [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
if (FBReg)
addFBReg(0);
else
addBReg(Reg.DwarfRegNo, 0);
// [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset].
// [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset].
// If Reg is a subregister we need to mask it out before subtracting.
if (Op && ((Op->getOp() == dwarf::DW_OP_plus) ||
(Op->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
int Offset = Op->getArg(0);
SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
ExprCursor.take();
break;
}
if (FBReg)
addFBReg(SignedOffset);
else
addBReg(Reg.DwarfRegNo, SignedOffset);
DwarfRegs.clear();
return true;
}
/// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".
static bool isMemoryLocation(DIExpressionCursor ExprCursor) {
while (ExprCursor) {
auto Op = ExprCursor.take();
switch (Op->getOp()) {
case dwarf::DW_OP_deref:
case dwarf::DW_OP_LLVM_fragment:
break;
default:
return false;
}
}
return true;
}
void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
unsigned FragmentOffsetInBits) {
// If we need to mask out a subregister, do it now, unless the next
// operation would emit an OpPiece anyway.
auto N = ExprCursor.peek();
if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment))
maskSubRegister();
while (ExprCursor) {
auto Op = ExprCursor.take();
// If we need to mask out a subregister, do it now, unless the next
// operation would emit an OpPiece anyway.
if (SubRegisterSizeInBits && Op->getOp() != dwarf::DW_OP_LLVM_fragment)
maskSubRegister();
switch (Op->getOp()) {
case dwarf::DW_OP_LLVM_fragment: {
unsigned SizeInBits = Op->getArg(1);
@ -281,50 +294,74 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
// location.
assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
// If \a addMachineReg already emitted DW_OP_piece operations to represent
// If addMachineReg already emitted DW_OP_piece operations to represent
// a super-register by splicing together sub-registers, subtract the size
// of the pieces that was already emitted.
SizeInBits -= OffsetInBits - FragmentOffset;
// If \a addMachineReg requested a DW_OP_bit_piece to stencil out a
// If addMachineReg requested a DW_OP_bit_piece to stencil out a
// sub-register that is smaller than the current fragment's size, use it.
if (SubRegisterSizeInBits)
SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);
// Emit a DW_OP_stack_value for implicit location descriptions.
if (LocationKind == Implicit)
addStackValue();
// Emit the DW_OP_piece.
addOpPiece(SizeInBits, SubRegisterOffsetInBits);
setSubRegisterPiece(0, 0);
break;
// Reset the location description kind.
LocationKind = Unknown;
return;
}
case dwarf::DW_OP_plus:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_plus_uconst);
emitUnsigned(Op->getArg(0));
break;
case dwarf::DW_OP_minus:
// There is no OP_minus_uconst.
assert(LocationKind != Register);
// There is no DW_OP_minus_uconst.
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Op->getArg(0));
emitOp(dwarf::DW_OP_minus);
break;
case dwarf::DW_OP_deref:
emitOp(dwarf::DW_OP_deref);
case dwarf::DW_OP_deref: {
assert(LocationKind != Register);
if (LocationKind != Memory && isMemoryLocation(ExprCursor))
// Turning this into a memory location description makes the deref
// implicit.
LocationKind = Memory;
else
emitOp(dwarf::DW_OP_deref);
break;
}
case dwarf::DW_OP_constu:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_constu);
emitUnsigned(Op->getArg(0));
break;
case dwarf::DW_OP_stack_value:
addStackValue();
assert(LocationKind == Unknown || LocationKind == Implicit);
LocationKind = Implicit;
break;
case dwarf::DW_OP_swap:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_swap);
break;
case dwarf::DW_OP_xderef:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_xderef);
break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
}
if (LocationKind == Implicit)
// Turn this into an implicit location description.
addStackValue();
}
/// add masking operations to stencil out a subregister.

View File

@ -72,6 +72,8 @@ class DIExpressionCursor {
}
/// Determine whether there are any operations left in this expression.
operator bool() const { return Start != End; }
DIExpression::expr_op_iterator begin() const { return Start; }
DIExpression::expr_op_iterator end() const { return End; }
/// Retrieve the fragment information, if any.
Optional<DIExpression::FragmentInfo> getFragmentInfo() const {
@ -102,6 +104,9 @@ class DwarfExpression {
unsigned SubRegisterSizeInBits = 0;
unsigned SubRegisterOffsetInBits = 0;
/// The kind of location description being produced.
enum { Unknown = 0, Register, Memory, Implicit } LocationKind = Unknown;
/// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
/// to represent a subregister.
void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
@ -122,7 +127,8 @@ class DwarfExpression {
/// current function.
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
/// Emit a DW_OP_reg operation.
/// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF
/// register location description.
void addReg(int DwarfReg, const char *Comment = nullptr);
/// Emit a DW_OP_breg operation.
void addBReg(int DwarfReg, int Offset);
@ -185,11 +191,18 @@ class DwarfExpression {
/// Emit an unsigned constant.
void addUnsignedConstant(const APInt &Value);
/// Lock this down to become a memory location description.
void setMemoryLocationKind() {
assert(LocationKind == Unknown);
LocationKind = Memory;
}
/// Emit a machine register location. As an optimization this may also consume
/// the prefix of a DwarfExpression if a more efficient representation for
/// combining the register location and the first operation exists.
///
/// \param FragmentOffsetInBits If this is one fragment out of a fragmented
/// \param FragmentOffsetInBits If this is one fragment out of a
/// fragmented
/// location, this is the offset of the
/// fragment inside the entire variable.
/// \return false if no DWARF register exists

View File

@ -27,6 +27,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Metadata.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
@ -73,8 +74,8 @@ bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
: DIEUnit(A->getDwarfVersion(), A->getPointerSize(), UnitTag), CUNode(Node),
Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr) {
: DIEUnit(A->getDwarfVersion(), A->MAI->getCodePointerSize(), UnitTag),
CUNode(Node), Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr) {
}
DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
@ -471,12 +472,13 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// variable's location.
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
if (Location.isIndirect())
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 9> Ops;
if (Location.isIndirect()) {
if (Location.isIndirect() && Location.getOffset()) {
Ops.push_back(dwarf::DW_OP_plus);
Ops.push_back(Location.getOffset());
Ops.push_back(dwarf::DW_OP_deref);
}
// If we started with a pointer to the __Block_byref... struct, then
// the first thing we need to do is dereference the pointer (DW_OP_deref).
@ -1546,7 +1548,7 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
Asm->OutStreamer->AddComment("DWARF Unit Type");
Asm->EmitInt8(UT);
Asm->OutStreamer->AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
Asm->EmitInt8(Asm->MAI->getCodePointerSize());
}
// We share one abbreviations table across all units so it's always at the
@ -1562,7 +1564,7 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
if (Version <= 4) {
Asm->OutStreamer->AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
Asm->EmitInt8(Asm->MAI->getCodePointerSize());
}
}

View File

@ -570,8 +570,14 @@ bool CodeGenPrepare::splitIndirectCriticalEdges(Function &F) {
ValueToValueMapTy VMap;
BasicBlock *DirectSucc = CloneBasicBlock(Target, VMap, ".clone", &F);
for (BasicBlock *Pred : OtherPreds)
Pred->getTerminator()->replaceUsesOfWith(Target, DirectSucc);
for (BasicBlock *Pred : OtherPreds) {
// If the target is a loop to itself, then the terminator of the split
// block needs to be updated.
if (Pred == Target)
BodyBlock->getTerminator()->replaceUsesOfWith(Target, DirectSucc);
else
Pred->getTerminator()->replaceUsesOfWith(Target, DirectSucc);
}
// Ok, now fix up the PHIs. We know the two blocks only have PHIs, and that
// they are clones, so the number of PHIs are the same.
@ -5059,16 +5065,14 @@ bool CodeGenPrepare::optimizeLoadExt(LoadInst *Load) {
if (!ShlC)
return false;
uint64_t ShiftAmt = ShlC->getLimitedValue(BitWidth - 1);
auto ShlDemandBits = APInt::getAllOnesValue(BitWidth).lshr(ShiftAmt);
DemandBits |= ShlDemandBits;
DemandBits.setLowBits(BitWidth - ShiftAmt);
break;
}
case llvm::Instruction::Trunc: {
EVT TruncVT = TLI->getValueType(*DL, I->getType());
unsigned TruncBitWidth = TruncVT.getSizeInBits();
auto TruncBits = APInt::getAllOnesValue(TruncBitWidth).zext(BitWidth);
DemandBits |= TruncBits;
DemandBits.setLowBits(TruncBitWidth);
break;
}

View File

@ -381,18 +381,19 @@ bool IRTranslator::translateInsertValue(const User &U,
uint64_t Offset = 8 * DL->getIndexedOffsetInType(Src->getType(), Indices);
unsigned Res = getOrCreateVReg(U);
const Value &Inserted = *U.getOperand(1);
MIRBuilder.buildInsert(Res, getOrCreateVReg(*Src), getOrCreateVReg(Inserted),
Offset);
unsigned Inserted = getOrCreateVReg(*U.getOperand(1));
MIRBuilder.buildInsert(Res, getOrCreateVReg(*Src), Inserted, Offset);
return true;
}
bool IRTranslator::translateSelect(const User &U,
MachineIRBuilder &MIRBuilder) {
MIRBuilder.buildSelect(getOrCreateVReg(U), getOrCreateVReg(*U.getOperand(0)),
getOrCreateVReg(*U.getOperand(1)),
getOrCreateVReg(*U.getOperand(2)));
unsigned Res = getOrCreateVReg(U);
unsigned Tst = getOrCreateVReg(*U.getOperand(0));
unsigned Op0 = getOrCreateVReg(*U.getOperand(1));
unsigned Op1 = getOrCreateVReg(*U.getOperand(2));
MIRBuilder.buildSelect(Res, Tst, Op0, Op1);
return true;
}
@ -984,9 +985,11 @@ bool IRTranslator::translateInsertElement(const User &U,
ValToVReg[&U] = Elt;
return true;
}
MIRBuilder.buildInsertVectorElement(
getOrCreateVReg(U), getOrCreateVReg(*U.getOperand(0)),
getOrCreateVReg(*U.getOperand(1)), getOrCreateVReg(*U.getOperand(2)));
unsigned Res = getOrCreateVReg(U);
unsigned Val = getOrCreateVReg(*U.getOperand(0));
unsigned Elt = getOrCreateVReg(*U.getOperand(1));
unsigned Idx = getOrCreateVReg(*U.getOperand(2));
MIRBuilder.buildInsertVectorElement(Res, Val, Elt, Idx);
return true;
}
@ -999,9 +1002,10 @@ bool IRTranslator::translateExtractElement(const User &U,
ValToVReg[&U] = Elt;
return true;
}
MIRBuilder.buildExtractVectorElement(getOrCreateVReg(U),
getOrCreateVReg(*U.getOperand(0)),
getOrCreateVReg(*U.getOperand(1)));
unsigned Res = getOrCreateVReg(U);
unsigned Val = getOrCreateVReg(*U.getOperand(0));
unsigned Idx = getOrCreateVReg(*U.getOperand(1));
MIRBuilder.buildExtractVectorElement(Res, Val, Idx);
return true;
}

View File

@ -68,23 +68,6 @@ bool InstructionSelector::constrainSelectedInstRegOperands(
return true;
}
Optional<int64_t>
InstructionSelector::getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI) const {
MachineInstr *MI = MRI.getVRegDef(VReg);
if (MI->getOpcode() != TargetOpcode::G_CONSTANT)
return None;
if (MI->getOperand(1).isImm())
return MI->getOperand(1).getImm();
if (MI->getOperand(1).isCImm() &&
MI->getOperand(1).getCImm()->getBitWidth() <= 64)
return MI->getOperand(1).getCImm()->getSExtValue();
return None;
}
bool InstructionSelector::isOperandImmEqual(
const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const {

View File

@ -24,6 +24,8 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <iterator>
#define DEBUG_TYPE "legalizer"
using namespace llvm;
@ -161,7 +163,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
// convergence for performance reasons.
bool Changed = false;
MachineBasicBlock::iterator NextMI;
for (auto &MBB : MF)
for (auto &MBB : MF) {
for (auto MI = MBB.begin(); MI != MBB.end(); MI = NextMI) {
// Get the next Instruction before we try to legalize, because there's a
// good chance MI will be deleted.
@ -171,18 +173,21 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
// and are assumed to be legal.
if (!isPreISelGenericOpcode(MI->getOpcode()))
continue;
unsigned NumNewInsns = 0;
SmallVector<MachineInstr *, 4> WorkList;
Helper.MIRBuilder.recordInsertions(
[&](MachineInstr *MI) { WorkList.push_back(MI); });
Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
++NumNewInsns;
WorkList.push_back(MI);
});
WorkList.push_back(&*MI);
bool Changed = false;
LegalizerHelper::LegalizeResult Res;
unsigned Idx = 0;
do {
Res = Helper.legalizeInstrStep(*WorkList[Idx]);
// Error out if we couldn't legalize this instruction. We may want to
// fall
// back to DAG ISel instead in the future.
// fall back to DAG ISel instead in the future.
if (Res == LegalizerHelper::UnableToLegalize) {
Helper.MIRBuilder.stopRecordingInsertions();
if (Res == LegalizerHelper::UnableToLegalize) {
@ -194,10 +199,21 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
}
Changed |= Res == LegalizerHelper::Legalized;
++Idx;
#ifndef NDEBUG
if (NumNewInsns) {
DEBUG(dbgs() << ".. .. Emitted " << NumNewInsns << " insns\n");
for (auto I = WorkList.end() - NumNewInsns, E = WorkList.end();
I != E; ++I)
DEBUG(dbgs() << ".. .. New MI: "; (*I)->print(dbgs()));
NumNewInsns = 0;
}
#endif
} while (Idx < WorkList.size());
Helper.MIRBuilder.stopRecordingInsertions();
}
}
MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
@ -207,7 +223,11 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
// good chance MI will be deleted.
NextMI = std::next(MI);
Changed |= combineExtracts(*MI, MRI, TII);
// combineExtracts erases MI.
if (combineExtracts(*MI, MRI, TII)) {
Changed = true;
continue;
}
Changed |= combineMerges(*MI, MRI, TII);
}
}

View File

@ -24,7 +24,7 @@
#include <sstream>
#define DEBUG_TYPE "legalize-mir"
#define DEBUG_TYPE "legalizer"
using namespace llvm;
@ -35,24 +35,34 @@ LegalizerHelper::LegalizerHelper(MachineFunction &MF)
LegalizerHelper::LegalizeResult
LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
auto Action = LI.getAction(MI, MRI);
switch (std::get<0>(Action)) {
case LegalizerInfo::Legal:
DEBUG(dbgs() << ".. Already legal\n");
return AlreadyLegal;
case LegalizerInfo::Libcall:
DEBUG(dbgs() << ".. Convert to libcall\n");
return libcall(MI);
case LegalizerInfo::NarrowScalar:
DEBUG(dbgs() << ".. Narrow scalar\n");
return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
case LegalizerInfo::WidenScalar:
DEBUG(dbgs() << ".. Widen scalar\n");
return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
case LegalizerInfo::Lower:
DEBUG(dbgs() << ".. Lower\n");
return lower(MI, std::get<1>(Action), std::get<2>(Action));
case LegalizerInfo::FewerElements:
DEBUG(dbgs() << ".. Reduce number of elements\n");
return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
case LegalizerInfo::Custom:
DEBUG(dbgs() << ".. Custom legalization\n");
return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
: UnableToLegalize;
default:
DEBUG(dbgs() << ".. Unable to legalize\n");
return UnableToLegalize;
}
}

View File

@ -592,7 +592,7 @@ MachineInstrBuilder MachineIRBuilder::buildInsertVectorElement(unsigned Res,
LLT EltTy = MRI->getType(Elt);
LLT IdxTy = MRI->getType(Idx);
assert(ResTy.isVector() && ValTy.isVector() && "invalid operand type");
assert(EltTy.isScalar() && IdxTy.isScalar() && "invalid operand type");
assert(IdxTy.isScalar() && "invalid operand type");
assert(ResTy.getNumElements() == ValTy.getNumElements() && "type mismatch");
assert(ResTy.getElementType() == EltTy && "type mismatch");
#endif
@ -612,7 +612,8 @@ MachineInstrBuilder MachineIRBuilder::buildExtractVectorElement(unsigned Res,
LLT ValTy = MRI->getType(Val);
LLT IdxTy = MRI->getType(Idx);
assert(ValTy.isVector() && "invalid operand type");
assert(ResTy.isScalar() && IdxTy.isScalar() && "invalid operand type");
assert((ResTy.isScalar() || ResTy.isPointer()) && "invalid operand type");
assert(IdxTy.isScalar() && "invalid operand type");
assert(ValTy.getElementType() == ResTy && "type mismatch");
#endif

View File

@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constants.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
@ -93,3 +94,19 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
R << Msg << ": " << ore::MNV("Inst", MI);
reportGISelFailure(MF, TPC, MORE, R);
}
Optional<int64_t> llvm::getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI) {
MachineInstr *MI = MRI.getVRegDef(VReg);
if (MI->getOpcode() != TargetOpcode::G_CONSTANT)
return None;
if (MI->getOperand(1).isImm())
return MI->getOperand(1).getImm();
if (MI->getOperand(1).isCImm() &&
MI->getOperand(1).getCImm()->getBitWidth() <= 64)
return MI->getOperand(1).getCImm()->getSExtValue();
return None;
}

View File

@ -888,20 +888,10 @@ void InlineSpiller::spillAroundUses(unsigned Reg) {
// Debug values are not allowed to affect codegen.
if (MI->isDebugValue()) {
// Modify DBG_VALUE now that the value is in a spill slot.
bool IsIndirect = MI->isIndirectDebugValue();
uint64_t Offset = IsIndirect ? MI->getOperand(1).getImm() : 0;
const MDNode *Var = MI->getDebugVariable();
const MDNode *Expr = MI->getDebugExpression();
DebugLoc DL = MI->getDebugLoc();
DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI);
MachineBasicBlock *MBB = MI->getParent();
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
BuildMI(*MBB, MBB->erase(MI), DL, TII.get(TargetOpcode::DBG_VALUE))
.addFrameIndex(StackSlot)
.addImm(Offset)
.addMetadata(Var)
.addMetadata(Expr);
DEBUG(dbgs() << "Modifying debug info due to spill:\t" << *MI);
buildDbgValueForSpill(*MBB, MI, *MI, StackSlot);
MBB->erase(MI);
continue;
}

View File

@ -21,10 +21,10 @@ using namespace llvm;
LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
if (auto VTy = dyn_cast<VectorType>(&Ty)) {
auto NumElements = VTy->getNumElements();
auto ScalarSizeInBits = VTy->getElementType()->getPrimitiveSizeInBits();
LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL);
if (NumElements == 1)
return LLT::scalar(ScalarSizeInBits);
return LLT::vector(NumElements, ScalarSizeInBits);
return ScalarTy;
return LLT::vector(NumElements, ScalarTy);
} else if (auto PTy = dyn_cast<PointerType>(&Ty)) {
return LLT::pointer(PTy->getAddressSpace(), DL.getTypeSizeInBits(&Ty));
} else if (Ty.isSized()) {

View File

@ -2351,3 +2351,31 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI);
}
MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig,
int FrameIndex) {
const MDNode *Var = Orig.getDebugVariable();
auto *Expr = cast_or_null<DIExpression>(Orig.getDebugExpression());
bool IsIndirect = Orig.isIndirectDebugValue();
uint64_t Offset = IsIndirect ? Orig.getOperand(1).getImm() : 0;
DebugLoc DL = Orig.getDebugLoc();
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
// If the DBG_VALUE already was a memory location, add an extra
// DW_OP_deref. Otherwise just turning this from a register into a
// memory/indirect location is sufficient.
if (IsIndirect) {
SmallVector<uint64_t, 8> Ops;
Ops.push_back(dwarf::DW_OP_deref);
if (Expr)
Ops.append(Expr->elements_begin(), Expr->elements_end());
Expr = DIExpression::get(Expr->getContext(), Ops);
}
return BuildMI(BB, I, DL, Orig.getDesc())
.addFrameIndex(FrameIndex)
.addImm(Offset)
.addMetadata(Var)
.addMetadata(Expr);
}

View File

@ -2030,6 +2030,8 @@ namespace {
void MachineVerifier::verifyStackFrame() {
unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode();
unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode();
if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u)
return;
SmallVector<StackStateOfBB, 8> SPState;
SPState.resize(MF->getNumBlockIDs());

View File

@ -304,19 +304,7 @@ void RAFast::spillVirtReg(MachineBasicBlock::iterator MI,
LiveDbgValueMap[LRI->VirtReg];
for (unsigned li = 0, le = LRIDbgValues.size(); li != le; ++li) {
MachineInstr *DBG = LRIDbgValues[li];
const MDNode *Var = DBG->getDebugVariable();
const MDNode *Expr = DBG->getDebugExpression();
bool IsIndirect = DBG->isIndirectDebugValue();
uint64_t Offset = IsIndirect ? DBG->getOperand(1).getImm() : 0;
DebugLoc DL = DBG->getDebugLoc();
assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
MachineInstr *NewDV =
BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::DBG_VALUE))
.addFrameIndex(FI)
.addImm(Offset)
.addMetadata(Var)
.addMetadata(Expr);
MachineInstr *NewDV = buildDbgValueForSpill(*MBB, MI, *DBG, FI);
assert(NewDV->getParent() == MBB && "dangling parent pointer");
(void)NewDV;
DEBUG(dbgs() << "Inserting debug info due to spill:" << "\n" << *NewDV);

View File

@ -550,7 +550,7 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack(
// Replace alloc with the new location.
replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB,
/*Deref=*/true, -Offset);
/*Deref=*/false, -Offset);
Arg->replaceAllUsesWith(NewArg);
IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode());
IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment());
@ -565,7 +565,7 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack(
if (Size == 0)
Size = 1; // Don't create zero-sized stack objects.
replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -Offset);
replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/false, -Offset);
replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset);
// Replace uses of the alloca with the new location.
@ -655,7 +655,7 @@ void SafeStack::moveDynamicAllocasToUnsafeStack(
if (AI->hasName() && isa<Instruction>(NewAI))
NewAI->takeName(AI);
replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/true);
replaceDbgDeclareForAlloca(AI, NewAI, DIB, /*Deref=*/false);
AI->replaceAllUsesWith(NewAI);
AI->eraseFromParent();
}

View File

@ -2146,7 +2146,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
if (N->getFlags()->hasNoUnsignedWrap())
return N0;
if (DAG.MaskedValueIsZero(N1, ~APInt::getSignBit(BitWidth))) {
if (DAG.MaskedValueIsZero(N1, ~APInt::getSignMask(BitWidth))) {
// N1 is either 0 or the minimum signed value. If the sub is NSW, then
// N1 must be 0 because negating the minimum signed value is undefined.
if (N->getFlags()->hasNoSignedWrap())
@ -3705,7 +3705,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
// fold (and (sign_extend_inreg x, i16 to i32), 1) -> (and x, 1)
// fold (and (sra)) -> (and (srl)) when possible.
if (!VT.isVector() && SimplifyDemandedBits(SDValue(N, 0)))
if (SimplifyDemandedBits(SDValue(N, 0)))
return SDValue(N, 0);
// fold (zext_inreg (extload x)) -> (zextload x)
@ -4225,8 +4225,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
return Load;
// Simplify the operands using demanded-bits information.
if (!VT.isVector() &&
SimplifyDemandedBits(SDValue(N, 0)))
if (SimplifyDemandedBits(SDValue(N, 0)))
return SDValue(N, 0);
return SDValue();
@ -5058,8 +5057,7 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
return Tmp;
// Simplify the expression using non-local knowledge.
if (!VT.isVector() &&
SimplifyDemandedBits(SDValue(N, 0)))
if (SimplifyDemandedBits(SDValue(N, 0)))
return SDValue(N, 0);
return SDValue();
@ -5350,7 +5348,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
Shift = DAG.getNode(ISD::SHL, DL, VT, N0.getOperand(0),
DAG.getConstant(c2 - c1, DL, N1.getValueType()));
} else {
Mask = Mask.lshr(c1 - c2);
Mask.lshrInPlace(c1 - c2);
SDLoc DL(N);
Shift = DAG.getNode(ISD::SRL, DL, VT, N0.getOperand(0),
DAG.getConstant(c1 - c2, DL, N1.getValueType()));
@ -5660,7 +5658,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
DAG.getConstant(ShiftAmt, DL0,
getShiftAmountTy(SmallVT)));
AddToWorklist(SmallShift.getNode());
APInt Mask = APInt::getAllOnesValue(OpSizeInBits).lshr(ShiftAmt);
APInt Mask = APInt::getLowBitsSet(OpSizeInBits, OpSizeInBits - ShiftAmt);
SDLoc DL(N);
return DAG.getNode(ISD::AND, DL, VT,
DAG.getNode(ISD::ANY_EXTEND, DL, VT, SmallShift),
@ -8300,11 +8298,11 @@ static SDValue foldBitcastedFPLogic(SDNode *N, SelectionDAG &DAG,
switch (N0.getOpcode()) {
case ISD::AND:
FPOpcode = ISD::FABS;
SignMask = ~APInt::getSignBit(SourceVT.getSizeInBits());
SignMask = ~APInt::getSignMask(SourceVT.getSizeInBits());
break;
case ISD::XOR:
FPOpcode = ISD::FNEG;
SignMask = APInt::getSignBit(SourceVT.getSizeInBits());
SignMask = APInt::getSignMask(SourceVT.getSizeInBits());
break;
// TODO: ISD::OR --> ISD::FNABS?
default:
@ -8415,7 +8413,7 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
if (N0.getValueType() == MVT::ppcf128 && !LegalTypes) {
assert(VT.getSizeInBits() == 128);
SDValue SignBit = DAG.getConstant(
APInt::getSignBit(VT.getSizeInBits() / 2), SDLoc(N0), MVT::i64);
APInt::getSignMask(VT.getSizeInBits() / 2), SDLoc(N0), MVT::i64);
SDValue FlipBit;
if (N0.getOpcode() == ISD::FNEG) {
FlipBit = SignBit;
@ -8435,7 +8433,7 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
AddToWorklist(FlipBits.getNode());
return DAG.getNode(ISD::XOR, DL, VT, NewConv, FlipBits);
}
APInt SignBit = APInt::getSignBit(VT.getSizeInBits());
APInt SignBit = APInt::getSignMask(VT.getSizeInBits());
if (N0.getOpcode() == ISD::FNEG)
return DAG.getNode(ISD::XOR, DL, VT,
NewConv, DAG.getConstant(SignBit, DL, VT));
@ -8483,7 +8481,7 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
}
if (N0.getValueType() == MVT::ppcf128 && !LegalTypes) {
APInt SignBit = APInt::getSignBit(VT.getSizeInBits() / 2);
APInt SignBit = APInt::getSignMask(VT.getSizeInBits() / 2);
SDValue Cst = DAG.getBitcast(VT, N0.getOperand(0));
AddToWorklist(Cst.getNode());
SDValue X = DAG.getBitcast(VT, N0.getOperand(1));
@ -8504,7 +8502,7 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
AddToWorklist(FlipBits.getNode());
return DAG.getNode(ISD::XOR, SDLoc(N), VT, Cst, FlipBits);
}
APInt SignBit = APInt::getSignBit(VT.getSizeInBits());
APInt SignBit = APInt::getSignMask(VT.getSizeInBits());
X = DAG.getNode(ISD::AND, SDLoc(X), VT,
X, DAG.getConstant(SignBit, SDLoc(X), VT));
AddToWorklist(X.getNode());
@ -8687,7 +8685,7 @@ ConstantFoldBITCASTofBUILD_VECTOR(SDNode *BV, EVT DstEltVT) {
for (unsigned j = 0; j != NumOutputsPerInput; ++j) {
APInt ThisVal = OpVal.trunc(DstBitSize);
Ops.push_back(DAG.getConstant(ThisVal, DL, DstEltVT));
OpVal = OpVal.lshr(DstBitSize);
OpVal.lshrInPlace(DstBitSize);
}
// For big endian targets, swap the order of the pieces of each element.
@ -10315,11 +10313,11 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
if (N0.getValueType().isVector()) {
// For a vector, get a mask such as 0x80... per scalar element
// and splat it.
SignMask = APInt::getSignBit(N0.getScalarValueSizeInBits());
SignMask = APInt::getSignMask(N0.getScalarValueSizeInBits());
SignMask = APInt::getSplat(IntVT.getSizeInBits(), SignMask);
} else {
// For a scalar, just generate 0x80...
SignMask = APInt::getSignBit(IntVT.getSizeInBits());
SignMask = APInt::getSignMask(IntVT.getSizeInBits());
}
SDLoc DL0(N0);
Int = DAG.getNode(ISD::XOR, DL0, IntVT, Int,
@ -10420,11 +10418,11 @@ SDValue DAGCombiner::visitFABS(SDNode *N) {
if (N0.getValueType().isVector()) {
// For a vector, get a mask such as 0x7f... per scalar element
// and splat it.
SignMask = ~APInt::getSignBit(N0.getScalarValueSizeInBits());
SignMask = ~APInt::getSignMask(N0.getScalarValueSizeInBits());
SignMask = APInt::getSplat(IntVT.getSizeInBits(), SignMask);
} else {
// For a scalar, just generate 0x7f...
SignMask = ~APInt::getSignBit(IntVT.getSizeInBits());
SignMask = ~APInt::getSignMask(IntVT.getSizeInBits());
}
SDLoc DL(N0);
Int = DAG.getNode(ISD::AND, DL, IntVT, Int,
@ -12375,6 +12373,27 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
return LHS.OffsetFromBase < RHS.OffsetFromBase;
});
// Store Merge attempts to merge the lowest stores. This generally
// works out as if successful, as the remaining stores are checked
// after the first collection of stores is merged. However, in the
// case that a non-mergeable store is found first, e.g., {p[-2],
// p[0], p[1], p[2], p[3]}, we would fail and miss the subsequent
// mergeable cases. To prevent this, we prune such stores from the
// front of StoreNodes here.
unsigned StartIdx = 0;
while ((StartIdx + 1 < StoreNodes.size()) &&
StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
StoreNodes[StartIdx + 1].OffsetFromBase)
++StartIdx;
// Bail if we don't have enough candidates to merge.
if (StartIdx + 1 >= StoreNodes.size())
return false;
if (StartIdx)
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + StartIdx);
// Scan the memory operations on the chain and find the first non-consecutive
// store memory address.
unsigned NumConsecutiveStores = 0;
@ -12485,39 +12504,52 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
// When extracting multiple vector elements, try to store them
// in one vector store rather than a sequence of scalar stores.
if (IsExtractVecSrc) {
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
unsigned FirstStoreAlign = FirstInChain->getAlignment();
unsigned NumStoresToMerge = 0;
bool IsVec = MemVT.isVector();
for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
unsigned StoreValOpcode = St->getValue().getOpcode();
// This restriction could be loosened.
// Bail out if any stored values are not elements extracted from a vector.
// It should be possible to handle mixed sources, but load sources need
// more careful handling (see the block of code below that handles
// consecutive loads).
if (StoreValOpcode != ISD::EXTRACT_VECTOR_ELT &&
StoreValOpcode != ISD::EXTRACT_SUBVECTOR)
return false;
bool RV = false;
while (StoreNodes.size() >= 2) {
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
unsigned FirstStoreAS = FirstInChain->getAddressSpace();
unsigned FirstStoreAlign = FirstInChain->getAlignment();
unsigned NumStoresToMerge = 0;
bool IsVec = MemVT.isVector();
for (unsigned i = 0; i < NumConsecutiveStores; ++i) {
StoreSDNode *St = cast<StoreSDNode>(StoreNodes[i].MemNode);
unsigned StoreValOpcode = St->getValue().getOpcode();
// This restriction could be loosened.
// Bail out if any stored values are not elements extracted from a
// vector. It should be possible to handle mixed sources, but load
// sources need more careful handling (see the block of code below that
// handles consecutive loads).
if (StoreValOpcode != ISD::EXTRACT_VECTOR_ELT &&
StoreValOpcode != ISD::EXTRACT_SUBVECTOR)
return false;
// Find a legal type for the vector store.
unsigned Elts = i + 1;
if (IsVec) {
// When merging vector stores, get the total number of elements.
Elts *= MemVT.getVectorNumElements();
// Find a legal type for the vector store.
unsigned Elts = i + 1;
if (IsVec) {
// When merging vector stores, get the total number of elements.
Elts *= MemVT.getVectorNumElements();
}
EVT Ty =
EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(), Elts);
bool IsFast;
if (TLI.isTypeLegal(Ty) &&
TLI.allowsMemoryAccess(Context, DL, Ty, FirstStoreAS,
FirstStoreAlign, &IsFast) &&
IsFast)
NumStoresToMerge = i + 1;
}
EVT Ty = EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(), Elts);
bool IsFast;
if (TLI.isTypeLegal(Ty) &&
TLI.allowsMemoryAccess(Context, DL, Ty, FirstStoreAS,
FirstStoreAlign, &IsFast) && IsFast)
NumStoresToMerge = i + 1;
}
return MergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumStoresToMerge,
false, true);
bool Merged = MergeStoresOfConstantsOrVecElts(
StoreNodes, MemVT, NumStoresToMerge, false, true);
if (!Merged)
break;
// Remove merged stores for next iteration.
StoreNodes.erase(StoreNodes.begin(),
StoreNodes.begin() + NumStoresToMerge);
RV = true;
NumConsecutiveStores -= NumStoresToMerge;
}
return RV;
}
// Below we handle the case of multiple consecutive stores that
@ -15122,9 +15154,9 @@ SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) {
// Extract the sub element from the constant bit mask.
if (DAG.getDataLayout().isBigEndian()) {
Bits = Bits.lshr((Split - SubIdx - 1) * NumSubBits);
Bits.lshrInPlace((Split - SubIdx - 1) * NumSubBits);
} else {
Bits = Bits.lshr(SubIdx * NumSubBits);
Bits.lshrInPlace(SubIdx * NumSubBits);
}
if (Split > 1)
@ -16004,7 +16036,7 @@ SDValue DAGCombiner::buildSqrtEstimate(SDValue Op, SDNodeFlags *Flags) {
/// Return true if base is a frame index, which is known not to alias with
/// anything but itself. Provides base object and offset as results.
static bool FindBaseOffset(SDValue Ptr, SDValue &Base, int64_t &Offset,
static bool findBaseOffset(SDValue Ptr, SDValue &Base, int64_t &Offset,
const GlobalValue *&GV, const void *&CV) {
// Assume it is a primitive operation.
Base = Ptr; Offset = 0; GV = nullptr; CV = nullptr;
@ -16057,53 +16089,56 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const {
return false;
// Gather base node and offset information.
SDValue Base1, Base2;
int64_t Offset1, Offset2;
const GlobalValue *GV1, *GV2;
const void *CV1, *CV2;
bool isFrameIndex1 = FindBaseOffset(Op0->getBasePtr(),
SDValue Base0, Base1;
int64_t Offset0, Offset1;
const GlobalValue *GV0, *GV1;
const void *CV0, *CV1;
bool IsFrameIndex0 = findBaseOffset(Op0->getBasePtr(),
Base0, Offset0, GV0, CV0);
bool IsFrameIndex1 = findBaseOffset(Op1->getBasePtr(),
Base1, Offset1, GV1, CV1);
bool isFrameIndex2 = FindBaseOffset(Op1->getBasePtr(),
Base2, Offset2, GV2, CV2);
// If they have a same base address then check to see if they overlap.
if (Base1 == Base2 || (GV1 && (GV1 == GV2)) || (CV1 && (CV1 == CV2)))
return !((Offset1 + (Op0->getMemoryVT().getSizeInBits() >> 3)) <= Offset2 ||
(Offset2 + (Op1->getMemoryVT().getSizeInBits() >> 3)) <= Offset1);
// If they have the same base address, then check to see if they overlap.
unsigned NumBytes0 = Op0->getMemoryVT().getSizeInBits() >> 3;
unsigned NumBytes1 = Op1->getMemoryVT().getSizeInBits() >> 3;
if (Base0 == Base1 || (GV0 && (GV0 == GV1)) || (CV0 && (CV0 == CV1)))
return !((Offset0 + NumBytes0) <= Offset1 ||
(Offset1 + NumBytes1) <= Offset0);
// It is possible for different frame indices to alias each other, mostly
// when tail call optimization reuses return address slots for arguments.
// To catch this case, look up the actual index of frame indices to compute
// the real alias relationship.
if (isFrameIndex1 && isFrameIndex2) {
if (IsFrameIndex0 && IsFrameIndex1) {
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
Offset0 += MFI.getObjectOffset(cast<FrameIndexSDNode>(Base0)->getIndex());
Offset1 += MFI.getObjectOffset(cast<FrameIndexSDNode>(Base1)->getIndex());
Offset2 += MFI.getObjectOffset(cast<FrameIndexSDNode>(Base2)->getIndex());
return !((Offset1 + (Op0->getMemoryVT().getSizeInBits() >> 3)) <= Offset2 ||
(Offset2 + (Op1->getMemoryVT().getSizeInBits() >> 3)) <= Offset1);
return !((Offset0 + NumBytes0) <= Offset1 ||
(Offset1 + NumBytes1) <= Offset0);
}
// Otherwise, if we know what the bases are, and they aren't identical, then
// we know they cannot alias.
if ((isFrameIndex1 || CV1 || GV1) && (isFrameIndex2 || CV2 || GV2))
if ((IsFrameIndex0 || CV0 || GV0) && (IsFrameIndex1 || CV1 || GV1))
return false;
// If we know required SrcValue1 and SrcValue2 have relatively large alignment
// compared to the size and offset of the access, we may be able to prove they
// do not alias. This check is conservative for now to catch cases created by
// do not alias. This check is conservative for now to catch cases created by
// splitting vector types.
if ((Op0->getOriginalAlignment() == Op1->getOriginalAlignment()) &&
(Op0->getSrcValueOffset() != Op1->getSrcValueOffset()) &&
(Op0->getMemoryVT().getSizeInBits() >> 3 ==
Op1->getMemoryVT().getSizeInBits() >> 3) &&
(Op0->getOriginalAlignment() > (Op0->getMemoryVT().getSizeInBits() >> 3))) {
int64_t OffAlign1 = Op0->getSrcValueOffset() % Op0->getOriginalAlignment();
int64_t OffAlign2 = Op1->getSrcValueOffset() % Op1->getOriginalAlignment();
int64_t SrcValOffset0 = Op0->getSrcValueOffset();
int64_t SrcValOffset1 = Op1->getSrcValueOffset();
unsigned OrigAlignment0 = Op0->getOriginalAlignment();
unsigned OrigAlignment1 = Op1->getOriginalAlignment();
if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
NumBytes0 == NumBytes1 && OrigAlignment0 > NumBytes0) {
int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0;
int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1;
// There is no overlap between these relatively aligned accesses of similar
// size, return no alias.
if ((OffAlign1 + (Op0->getMemoryVT().getSizeInBits() >> 3)) <= OffAlign2 ||
(OffAlign2 + (Op1->getMemoryVT().getSizeInBits() >> 3)) <= OffAlign1)
// size. Return no alias.
if ((OffAlign0 + NumBytes0) <= OffAlign1 ||
(OffAlign1 + NumBytes1) <= OffAlign0)
return false;
}
@ -16115,19 +16150,17 @@ bool DAGCombiner::isAlias(LSBaseSDNode *Op0, LSBaseSDNode *Op1) const {
CombinerAAOnlyFunc != DAG.getMachineFunction().getName())
UseAA = false;
#endif
if (UseAA &&
Op0->getMemOperand()->getValue() && Op1->getMemOperand()->getValue()) {
// Use alias analysis information.
int64_t MinOffset = std::min(Op0->getSrcValueOffset(),
Op1->getSrcValueOffset());
int64_t Overlap1 = (Op0->getMemoryVT().getSizeInBits() >> 3) +
Op0->getSrcValueOffset() - MinOffset;
int64_t Overlap2 = (Op1->getMemoryVT().getSizeInBits() >> 3) +
Op1->getSrcValueOffset() - MinOffset;
int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
int64_t Overlap0 = NumBytes0 + SrcValOffset0 - MinOffset;
int64_t Overlap1 = NumBytes1 + SrcValOffset1 - MinOffset;
AliasResult AAResult =
AA.alias(MemoryLocation(Op0->getMemOperand()->getValue(), Overlap1,
AA.alias(MemoryLocation(Op0->getMemOperand()->getValue(), Overlap0,
UseTBAA ? Op0->getAAInfo() : AAMDNodes()),
MemoryLocation(Op1->getMemOperand()->getValue(), Overlap2,
MemoryLocation(Op1->getMemOperand()->getValue(), Overlap1,
UseTBAA ? Op1->getAAInfo() : AAMDNodes()));
if (AAResult == NoAlias)
return false;

View File

@ -1164,9 +1164,11 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
"Expected inlined-at fields to agree");
if (Op->isReg()) {
Op->setIsDebug(true);
// A dbg.declare describes the address of a source variable, so lower it
// into an indirect DBG_VALUE.
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::DBG_VALUE), false, Op->getReg(), 0,
DI->getVariable(), DI->getExpression());
TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true,
Op->getReg(), 0, DI->getVariable(), DI->getExpression());
} else
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(TargetOpcode::DBG_VALUE))

View File

@ -1343,7 +1343,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
// Convert to an integer of the same size.
if (TLI.isTypeLegal(IVT)) {
State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value);
State.SignMask = APInt::getSignBit(NumBits);
State.SignMask = APInt::getSignMask(NumBits);
State.SignBit = NumBits - 1;
return;
}
@ -2984,7 +2984,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
EVT NVT = Node->getValueType(0);
APFloat apf(DAG.EVTToAPFloatSemantics(VT),
APInt::getNullValue(VT.getSizeInBits()));
APInt x = APInt::getSignBit(NVT.getSizeInBits());
APInt x = APInt::getSignMask(NVT.getSizeInBits());
(void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven);
Tmp1 = DAG.getConstantFP(apf, dl, VT);
Tmp2 = DAG.getSetCC(dl, getSetCCResultType(VT),

View File

@ -72,7 +72,7 @@ bool DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break;
case ISD::ConstantFP: R = SoftenFloatRes_ConstantFP(N, ResNo); break;
case ISD::EXTRACT_VECTOR_ELT:
R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N); break;
R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N, ResNo); break;
case ISD::FABS: R = SoftenFloatRes_FABS(N, ResNo); break;
case ISD::FMINNUM: R = SoftenFloatRes_FMINNUM(N); break;
case ISD::FMAXNUM: R = SoftenFloatRes_FMAXNUM(N); break;
@ -171,7 +171,10 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_ConstantFP(SDNode *N, unsigned ResNo) {
}
}
SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) {
SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N, unsigned ResNo) {
// When LegalInHWReg, keep the extracted value in register.
if (isLegalInHWReg(N->getValueType(ResNo)))
return SDValue(N, ResNo);
SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0));
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
NewOp.getValueType().getVectorElementType(),

View File

@ -925,9 +925,9 @@ SDValue DAGTypeLegalizer::BitConvertVectorToIntegerVector(SDValue Op) {
assert(Op.getValueType().isVector() && "Only applies to vectors!");
unsigned EltWidth = Op.getScalarValueSizeInBits();
EVT EltNVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth);
unsigned NumElts = Op.getValueType().getVectorNumElements();
auto EltCnt = Op.getValueType().getVectorElementCount();
return DAG.getNode(ISD::BITCAST, SDLoc(Op),
EVT::getVectorVT(*DAG.getContext(), EltNVT, NumElts), Op);
EVT::getVectorVT(*DAG.getContext(), EltNVT, EltCnt), Op);
}
SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op,

View File

@ -428,7 +428,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SoftenFloatRes_BITCAST(SDNode *N, unsigned ResNo);
SDValue SoftenFloatRes_BUILD_PAIR(SDNode *N);
SDValue SoftenFloatRes_ConstantFP(SDNode *N, unsigned ResNo);
SDValue SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N);
SDValue SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N, unsigned ResNo);
SDValue SoftenFloatRes_FABS(SDNode *N, unsigned ResNo);
SDValue SoftenFloatRes_FMINNUM(SDNode *N);
SDValue SoftenFloatRes_FMAXNUM(SDNode *N);

View File

@ -1293,12 +1293,9 @@ void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
if ((NumElements & 1) == 0 &&
SrcVT.getSizeInBits() * 2 < DestVT.getSizeInBits()) {
LLVMContext &Ctx = *DAG.getContext();
EVT NewSrcVT = EVT::getVectorVT(
Ctx, EVT::getIntegerVT(
Ctx, SrcVT.getScalarSizeInBits() * 2),
NumElements);
EVT SplitSrcVT =
EVT::getVectorVT(Ctx, SrcVT.getVectorElementType(), NumElements / 2);
EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
EVT SplitLoVT, SplitHiVT;
std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
@ -3012,8 +3009,8 @@ SDValue DAGTypeLegalizer::WidenVSELECTAndMask(SDNode *N) {
// Don't touch if this will be scalarized.
EVT FinalVT = VSelVT;
while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
FinalVT = EVT::getVectorVT(Ctx, FinalVT.getVectorElementType(),
FinalVT.getVectorNumElements() / 2);
FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
if (FinalVT.getVectorNumElements() == 1)
return SDValue();

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