Merge llvm, clang, lld, lldb, compiler-rt and libc++ release_70 branch

r348686 (effectively 7.0.1 rc3), resolve conflicts, and bump version
numbers.

PR:		230240, 230355
This commit is contained in:
Dimitry Andric 2018-12-09 11:36:04 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang700-import/; revision=341763
57 changed files with 645 additions and 312 deletions

View File

@ -352,7 +352,6 @@ struct FileDescriptor {
~FileDescriptor() { close(); } ~FileDescriptor() { close(); }
FileDescriptor() = default;
FileDescriptor(FileDescriptor const&) = delete; FileDescriptor(FileDescriptor const&) = delete;
FileDescriptor& operator=(FileDescriptor const&) = delete; FileDescriptor& operator=(FileDescriptor const&) = delete;

View File

@ -30,8 +30,6 @@ class GSIHashIterator
GSIHashIterator, FixedStreamArrayIterator<PSHashRecord>, GSIHashIterator, FixedStreamArrayIterator<PSHashRecord>,
std::random_access_iterator_tag, const uint32_t> { std::random_access_iterator_tag, const uint32_t> {
public: public:
GSIHashIterator() = default;
template <typename T> template <typename T>
GSIHashIterator(T &&v) GSIHashIterator(T &&v)
: GSIHashIterator::iterator_adaptor_base(std::forward<T &&>(v)) {} : GSIHashIterator::iterator_adaptor_base(std::forward<T &&>(v)) {}

View File

@ -49,7 +49,7 @@ class ModuleDebugStreamRef {
BinarySubstreamRef getC13LinesSubstream() const; BinarySubstreamRef getC13LinesSubstream() const;
BinarySubstreamRef getGlobalRefsSubstream() const; BinarySubstreamRef getGlobalRefsSubstream() const;
ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = default; ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = delete;
iterator_range<DebugSubsectionIterator> subsections() const; iterator_range<DebugSubsectionIterator> subsections() const;
codeview::DebugSubsectionArray getSubsectionsArray() const { codeview::DebugSubsectionArray getSubsectionsArray() const {

View File

@ -126,7 +126,7 @@ class MaterializationResponsibility {
public: public:
MaterializationResponsibility(MaterializationResponsibility &&) = default; MaterializationResponsibility(MaterializationResponsibility &&) = default;
MaterializationResponsibility & MaterializationResponsibility &
operator=(MaterializationResponsibility &&) = default; operator=(MaterializationResponsibility &&) = delete;
/// Destruct a MaterializationResponsibility instance. In debug mode /// Destruct a MaterializationResponsibility instance. In debug mode
/// this asserts that all symbols being tracked have been either /// this asserts that all symbols being tracked have been either

View File

@ -70,8 +70,7 @@ class OrcRemoteTargetClient
RemoteRTDyldMemoryManager & RemoteRTDyldMemoryManager &
operator=(const RemoteRTDyldMemoryManager &) = delete; operator=(const RemoteRTDyldMemoryManager &) = delete;
RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default; RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
RemoteRTDyldMemoryManager & RemoteRTDyldMemoryManager &operator=(RemoteRTDyldMemoryManager &&) = delete;
operator=(RemoteRTDyldMemoryManager &&) = default;
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, unsigned SectionID,

View File

@ -165,6 +165,11 @@ class MCAsmBackend {
return 0; return 0;
} }
/// Check whether a given symbol has been flagged with MICROMIPS flag.
virtual bool isMicroMips(const MCSymbol *Sym) const {
return false;
}
/// Handles all target related code padding when starting to write a new /// Handles all target related code padding when starting to write a new
/// basic block to an object file. /// basic block to an object file.
/// ///

View File

@ -641,8 +641,6 @@ class LineCoverageIterator
this->operator++(); this->operator++();
} }
LineCoverageIterator &operator=(const LineCoverageIterator &R) = default;
bool operator==(const LineCoverageIterator &R) const { bool operator==(const LineCoverageIterator &R) const {
return &CD == &R.CD && Next == R.Next && Ended == R.Ended; return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
} }

View File

@ -1186,6 +1186,20 @@ struct SemiNCAInfo {
<< '\t' << U << "\n"); << '\t' << U << "\n");
LLVM_DEBUG(dbgs() << "\n"); LLVM_DEBUG(dbgs() << "\n");
// Recalculate the DominatorTree when the number of updates
// exceeds a threshold, which usually makes direct updating slower than
// recalculation. We select this threshold proportional to the
// size of the DominatorTree. The constant is selected
// by choosing the one with an acceptable performance on some real-world
// inputs.
// Make unittests of the incremental algorithm work
if (DT.DomTreeNodes.size() <= 100) {
if (NumLegalized > DT.DomTreeNodes.size())
CalculateFromScratch(DT, &BUI);
} else if (NumLegalized > DT.DomTreeNodes.size() / 40)
CalculateFromScratch(DT, &BUI);
// If the DominatorTree was recalculated at some point, stop the batch // If the DominatorTree was recalculated at some point, stop the batch
// updates. Full recalculations ignore batch updates and look at the actual // updates. Full recalculations ignore batch updates and look at the actual
// CFG. // CFG.

View File

@ -76,6 +76,10 @@ class SSAUpdater {
/// block. /// block.
bool HasValueForBlock(BasicBlock *BB) const; bool HasValueForBlock(BasicBlock *BB) const;
/// Return the value for the specified block if the SSAUpdater has one,
/// otherwise return nullptr.
Value *FindValueForBlock(BasicBlock *BB) const;
/// Construct SSA form, materializing a value that is live at the end /// Construct SSA form, materializing a value that is live at the end
/// of the specified block. /// of the specified block.
Value *GetValueAtEndOfBlock(BasicBlock *BB); Value *GetValueAtEndOfBlock(BasicBlock *BB);

View File

@ -357,10 +357,9 @@ class SSAUpdaterImpl {
BBInfo *Info = *I; BBInfo *Info = *I;
if (Info->DefBB != Info) { if (Info->DefBB != Info) {
// Record the available value at join nodes to speed up subsequent // Record the available value to speed up subsequent uses of this
// uses of this SSAUpdater for the same value. // SSAUpdater for the same value.
if (Info->NumPreds > 1) (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal;
(*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal;
continue; continue;
} }

View File

@ -119,7 +119,6 @@ class MemoryLocOrCall {
public: public:
bool IsCall = false; bool IsCall = false;
MemoryLocOrCall() = default;
MemoryLocOrCall(MemoryUseOrDef *MUD) MemoryLocOrCall(MemoryUseOrDef *MUD)
: MemoryLocOrCall(MUD->getMemoryInst()) {} : MemoryLocOrCall(MUD->getMemoryInst()) {}
MemoryLocOrCall(const MemoryUseOrDef *MUD) MemoryLocOrCall(const MemoryUseOrDef *MUD)

View File

@ -1156,10 +1156,11 @@ MCSection *TargetLoweringObjectFileCOFF::SelectSectionForGlobal(
MCSymbol *Sym = TM.getSymbol(ComdatGV); MCSymbol *Sym = TM.getSymbol(ComdatGV);
StringRef COMDATSymName = Sym->getName(); StringRef COMDATSymName = Sym->getName();
// Append "$symbol" to the section name when targetting mingw. The ld.bfd // Append "$symbol" to the section name *before* IR-level mangling is
// applied when targetting mingw. This is what GCC does, and the ld.bfd
// COFF linker will not properly handle comdats otherwise. // COFF linker will not properly handle comdats otherwise.
if (getTargetTriple().isWindowsGNUEnvironment()) if (getTargetTriple().isWindowsGNUEnvironment())
raw_svector_ostream(Name) << '$' << COMDATSymName; raw_svector_ostream(Name) << '$' << ComdatGV->getName();
return getContext().getCOFFSection(Name, Characteristics, Kind, return getContext().getCOFFSection(Name, Characteristics, Kind,
COMDATSymName, Selection, UniqueID); COMDATSymName, Selection, UniqueID);

View File

@ -275,7 +275,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
uint64_t Size = I->getCommonSize(); uint64_t Size = I->getCommonSize();
if (!CommonAlign) if (!CommonAlign)
CommonAlign = Align; CommonAlign = Align;
CommonSize += alignTo(CommonSize, Align) + Size; CommonSize = alignTo(CommonSize, Align) + Size;
CommonSymbolsToAllocate.push_back(*I); CommonSymbolsToAllocate.push_back(*I);
} }
} else } else

View File

@ -524,6 +524,11 @@ static void AttemptToFoldSymbolOffsetDifference(
if (Asm->isThumbFunc(&SA)) if (Asm->isThumbFunc(&SA))
Addend |= 1; Addend |= 1;
// If symbol is labeled as micromips, we set low-bit to ensure
// correct offset in .gcc_except_table
if (Asm->getBackend().isMicroMips(&SA))
Addend |= 1;
// Clear the symbol expr pointers to indicate we have folded these // Clear the symbol expr pointers to indicate we have folded these
// operands. // operands.
A = B = nullptr; A = B = nullptr;

View File

@ -1515,39 +1515,50 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
/// The CCMP/CCMN/FCCMP/FCCMPE instructions allow the conditional execution of /// The CCMP/CCMN/FCCMP/FCCMPE instructions allow the conditional execution of
/// a comparison. They set the NZCV flags to a predefined value if their /// a comparison. They set the NZCV flags to a predefined value if their
/// predicate is false. This allows to express arbitrary conjunctions, for /// predicate is false. This allows to express arbitrary conjunctions, for
/// example "cmp 0 (and (setCA (cmp A)) (setCB (cmp B))))" /// example "cmp 0 (and (setCA (cmp A)) (setCB (cmp B)))"
/// expressed as: /// expressed as:
/// cmp A /// cmp A
/// ccmp B, inv(CB), CA /// ccmp B, inv(CB), CA
/// check for CB flags /// check for CB flags
/// ///
/// In general we can create code for arbitrary "... (and (and A B) C)" /// This naturally lets us implement chains of AND operations with SETCC
/// sequences. We can also implement some "or" expressions, because "(or A B)" /// operands. And we can even implement some other situations by transforming
/// is equivalent to "not (and (not A) (not B))" and we can implement some /// them:
/// negation operations: /// - We can implement (NEG SETCC) i.e. negating a single comparison by
/// We can negate the results of a single comparison by inverting the flags /// negating the flags used in a CCMP/FCCMP operations.
/// used when the predicate fails and inverting the flags tested in the next /// - We can negate the result of a whole chain of CMP/CCMP/FCCMP operations
/// instruction; We can also negate the results of the whole previous /// by negating the flags we test for afterwards. i.e.
/// conditional compare sequence by inverting the flags tested in the next /// NEG (CMP CCMP CCCMP ...) can be implemented.
/// instruction. However there is no way to negate the result of a partial /// - Note that we can only ever negate all previously processed results.
/// sequence. /// What we can not implement by flipping the flags to test is a negation
/// of two sub-trees (because the negation affects all sub-trees emitted so
/// far, so the 2nd sub-tree we emit would also affect the first).
/// With those tools we can implement some OR operations:
/// - (OR (SETCC A) (SETCC B)) can be implemented via:
/// NEG (AND (NEG (SETCC A)) (NEG (SETCC B)))
/// - After transforming OR to NEG/AND combinations we may be able to use NEG
/// elimination rules from earlier to implement the whole thing as a
/// CCMP/FCCMP chain.
/// ///
/// Therefore on encountering an "or" expression we can negate the subtree on /// As complete example:
/// one side and have to be able to push the negate to the leafs of the subtree /// or (or (setCA (cmp A)) (setCB (cmp B)))
/// on the other side (see also the comments in code). As complete example: /// (and (setCC (cmp C)) (setCD (cmp D)))"
/// "or (or (setCA (cmp A)) (setCB (cmp B))) /// can be reassociated to:
/// (and (setCC (cmp C)) (setCD (cmp D)))" /// or (and (setCC (cmp C)) setCD (cmp D))
/// is transformed to // (or (setCA (cmp A)) (setCB (cmp B)))
/// "not (and (not (and (setCC (cmp C)) (setCC (cmp D)))) /// can be transformed to:
/// (and (not (setCA (cmp A)) (not (setCB (cmp B))))))" /// not (and (not (and (setCC (cmp C)) (setCD (cmp D))))
/// and implemented as: /// (and (not (setCA (cmp A)) (not (setCB (cmp B))))))"
/// which can be implemented as:
/// cmp C /// cmp C
/// ccmp D, inv(CD), CC /// ccmp D, inv(CD), CC
/// ccmp A, CA, inv(CD) /// ccmp A, CA, inv(CD)
/// ccmp B, CB, inv(CA) /// ccmp B, CB, inv(CA)
/// check for CB flags /// check for CB flags
/// A counterexample is "or (and A B) (and C D)" which cannot be implemented ///
/// by conditional compare sequences. /// A counterexample is "or (and A B) (and C D)" which translates to
/// not (and (not (and (not A) (not B))) (not (and (not C) (not D)))), we
/// can only implement 1 of the inner (not) operations, but not both!
/// @{ /// @{
/// Create a conditional comparison; Use CCMP, CCMN or FCCMP as appropriate. /// Create a conditional comparison; Use CCMP, CCMN or FCCMP as appropriate.
@ -1585,14 +1596,23 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
return DAG.getNode(Opcode, DL, MVT_CC, LHS, RHS, NZCVOp, Condition, CCOp); return DAG.getNode(Opcode, DL, MVT_CC, LHS, RHS, NZCVOp, Condition, CCOp);
} }
/// Returns true if @p Val is a tree of AND/OR/SETCC operations. /// Returns true if @p Val is a tree of AND/OR/SETCC operations that can be
/// CanPushNegate is set to true if we can push a negate operation through /// expressed as a conjunction. See \ref AArch64CCMP.
/// the tree in a was that we are left with AND operations and negate operations /// \param CanNegate Set to true if we can negate the whole sub-tree just by
/// at the leafs only. i.e. "not (or (or x y) z)" can be changed to /// changing the conditions on the SETCC tests.
/// "and (and (not x) (not y)) (not z)"; "not (or (and x y) z)" cannot be /// (this means we can call emitConjunctionRec() with
/// brought into such a form. /// Negate==true on this sub-tree)
static bool isConjunctionDisjunctionTree(const SDValue Val, bool &CanNegate, /// \param MustBeFirst Set to true if this subtree needs to be negated and we
unsigned Depth = 0) { /// cannot do the negation naturally. We are required to
/// emit the subtree first in this case.
/// \param WillNegate Is true if are called when the result of this
/// subexpression must be negated. This happens when the
/// outer expression is an OR. We can use this fact to know
/// that we have a double negation (or (or ...) ...) that
/// can be implemented for free.
static bool canEmitConjunction(const SDValue Val, bool &CanNegate,
bool &MustBeFirst, bool WillNegate,
unsigned Depth = 0) {
if (!Val.hasOneUse()) if (!Val.hasOneUse())
return false; return false;
unsigned Opcode = Val->getOpcode(); unsigned Opcode = Val->getOpcode();
@ -1600,39 +1620,44 @@ static bool isConjunctionDisjunctionTree(const SDValue Val, bool &CanNegate,
if (Val->getOperand(0).getValueType() == MVT::f128) if (Val->getOperand(0).getValueType() == MVT::f128)
return false; return false;
CanNegate = true; CanNegate = true;
MustBeFirst = false;
return true; return true;
} }
// Protect against exponential runtime and stack overflow. // Protect against exponential runtime and stack overflow.
if (Depth > 6) if (Depth > 6)
return false; return false;
if (Opcode == ISD::AND || Opcode == ISD::OR) { if (Opcode == ISD::AND || Opcode == ISD::OR) {
bool IsOR = Opcode == ISD::OR;
SDValue O0 = Val->getOperand(0); SDValue O0 = Val->getOperand(0);
SDValue O1 = Val->getOperand(1); SDValue O1 = Val->getOperand(1);
bool CanNegateL; bool CanNegateL;
if (!isConjunctionDisjunctionTree(O0, CanNegateL, Depth+1)) bool MustBeFirstL;
if (!canEmitConjunction(O0, CanNegateL, MustBeFirstL, IsOR, Depth+1))
return false; return false;
bool CanNegateR; bool CanNegateR;
if (!isConjunctionDisjunctionTree(O1, CanNegateR, Depth+1)) bool MustBeFirstR;
if (!canEmitConjunction(O1, CanNegateR, MustBeFirstR, IsOR, Depth+1))
return false; return false;
if (Opcode == ISD::OR) { if (MustBeFirstL && MustBeFirstR)
// For an OR expression we need to be able to negate at least one side or return false;
// we cannot do the transformation at all.
if (IsOR) {
// For an OR expression we need to be able to naturally negate at least
// one side or we cannot do the transformation at all.
if (!CanNegateL && !CanNegateR) if (!CanNegateL && !CanNegateR)
return false; return false;
// We can however change a (not (or x y)) to (and (not x) (not y)) if we // If we the result of the OR will be negated and we can naturally negate
// can negate the x and y subtrees. // the leafs, then this sub-tree as a whole negates naturally.
CanNegate = CanNegateL && CanNegateR; CanNegate = WillNegate && CanNegateL && CanNegateR;
// If we cannot naturally negate the whole sub-tree, then this must be
// emitted first.
MustBeFirst = !CanNegate;
} else { } else {
// If the operands are OR expressions then we finally need to negate their assert(Opcode == ISD::AND && "Must be OR or AND");
// outputs, we can only do that for the operand with emitted last by // We cannot naturally negate an AND operation.
// negating OutCC, not for both operands.
bool NeedsNegOutL = O0->getOpcode() == ISD::OR;
bool NeedsNegOutR = O1->getOpcode() == ISD::OR;
if (NeedsNegOutL && NeedsNegOutR)
return false;
// We cannot negate an AND operation (it would become an OR),
CanNegate = false; CanNegate = false;
MustBeFirst = MustBeFirstL || MustBeFirstR;
} }
return true; return true;
} }
@ -1645,11 +1670,9 @@ static bool isConjunctionDisjunctionTree(const SDValue Val, bool &CanNegate,
/// and conditional compare operations. @returns an NZCV flags producing node /// and conditional compare operations. @returns an NZCV flags producing node
/// and sets @p OutCC to the flags that should be tested or returns SDValue() if /// and sets @p OutCC to the flags that should be tested or returns SDValue() if
/// transformation was not possible. /// transformation was not possible.
/// On recursive invocations @p PushNegate may be set to true to have negation /// \p Negate is true if we want this sub-tree being negated just by changing
/// effects pushed to the tree leafs; @p Predicate is an NZCV flag predicate /// SETCC conditions.
/// for the comparisons in the current subtree; @p Depth limits the search static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val,
/// depth to avoid stack overflow.
static SDValue emitConjunctionDisjunctionTreeRec(SelectionDAG &DAG, SDValue Val,
AArch64CC::CondCode &OutCC, bool Negate, SDValue CCOp, AArch64CC::CondCode &OutCC, bool Negate, SDValue CCOp,
AArch64CC::CondCode Predicate) { AArch64CC::CondCode Predicate) {
// We're at a tree leaf, produce a conditional comparison operation. // We're at a tree leaf, produce a conditional comparison operation.
@ -1690,76 +1713,85 @@ static SDValue emitConjunctionDisjunctionTreeRec(SelectionDAG &DAG, SDValue Val,
return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL, return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL,
DAG); DAG);
} }
assert((Opcode == ISD::AND || (Opcode == ISD::OR && Val->hasOneUse())) && assert(Val->hasOneUse() && "Valid conjunction/disjunction tree");
"Valid conjunction/disjunction tree");
bool IsOR = Opcode == ISD::OR;
// Check if both sides can be transformed.
SDValue LHS = Val->getOperand(0); SDValue LHS = Val->getOperand(0);
bool CanNegateL;
bool MustBeFirstL;
bool ValidL = canEmitConjunction(LHS, CanNegateL, MustBeFirstL, IsOR);
assert(ValidL && "Valid conjunction/disjunction tree");
(void)ValidL;
SDValue RHS = Val->getOperand(1); SDValue RHS = Val->getOperand(1);
bool CanNegateR;
bool MustBeFirstR;
bool ValidR = canEmitConjunction(RHS, CanNegateR, MustBeFirstR, IsOR);
assert(ValidR && "Valid conjunction/disjunction tree");
(void)ValidR;
// In case of an OR we need to negate our operands and the result. // Swap sub-tree that must come first to the right side.
// (A v B) <=> not(not(A) ^ not(B)) if (MustBeFirstL) {
bool NegateOpsAndResult = Opcode == ISD::OR; assert(!MustBeFirstR && "Valid conjunction/disjunction tree");
// We can negate the results of all previous operations by inverting the std::swap(LHS, RHS);
// predicate flags giving us a free negation for one side. The other side std::swap(CanNegateL, CanNegateR);
// must be negatable by itself. std::swap(MustBeFirstL, MustBeFirstR);
if (NegateOpsAndResult) {
// See which side we can negate.
bool CanNegateL;
bool isValidL = isConjunctionDisjunctionTree(LHS, CanNegateL);
assert(isValidL && "Valid conjunction/disjunction tree");
(void)isValidL;
#ifndef NDEBUG
bool CanNegateR;
bool isValidR = isConjunctionDisjunctionTree(RHS, CanNegateR);
assert(isValidR && "Valid conjunction/disjunction tree");
assert((CanNegateL || CanNegateR) && "Valid conjunction/disjunction tree");
#endif
// Order the side which we cannot negate to RHS so we can emit it first.
if (!CanNegateL)
std::swap(LHS, RHS);
} else {
bool NeedsNegOutL = LHS->getOpcode() == ISD::OR;
assert((!NeedsNegOutL || RHS->getOpcode() != ISD::OR) &&
"Valid conjunction/disjunction tree");
// Order the side where we need to negate the output flags to RHS so it
// gets emitted first.
if (NeedsNegOutL)
std::swap(LHS, RHS);
} }
// Emit RHS. If we want to negate the tree we only need to push a negate bool NegateR;
// through if we are already in a PushNegate case, otherwise we can negate bool NegateAfterR;
// the "flags to test" afterwards. bool NegateL;
bool NegateAfterAll;
if (Opcode == ISD::OR) {
// Swap the sub-tree that we can negate naturally to the left.
if (!CanNegateL) {
assert(CanNegateR && "at least one side must be negatable");
assert(!MustBeFirstR && "invalid conjunction/disjunction tree");
assert(!Negate);
std::swap(LHS, RHS);
NegateR = false;
NegateAfterR = true;
} else {
// Negate the left sub-tree if possible, otherwise negate the result.
NegateR = CanNegateR;
NegateAfterR = !CanNegateR;
}
NegateL = true;
NegateAfterAll = !Negate;
} else {
assert(Opcode == ISD::AND && "Valid conjunction/disjunction tree");
assert(!Negate && "Valid conjunction/disjunction tree");
NegateL = false;
NegateR = false;
NegateAfterR = false;
NegateAfterAll = false;
}
// Emit sub-trees.
AArch64CC::CondCode RHSCC; AArch64CC::CondCode RHSCC;
SDValue CmpR = emitConjunctionDisjunctionTreeRec(DAG, RHS, RHSCC, Negate, SDValue CmpR = emitConjunctionRec(DAG, RHS, RHSCC, NegateR, CCOp, Predicate);
CCOp, Predicate); if (NegateAfterR)
if (NegateOpsAndResult && !Negate)
RHSCC = AArch64CC::getInvertedCondCode(RHSCC); RHSCC = AArch64CC::getInvertedCondCode(RHSCC);
// Emit LHS. We may need to negate it. SDValue CmpL = emitConjunctionRec(DAG, LHS, OutCC, NegateL, CmpR, RHSCC);
SDValue CmpL = emitConjunctionDisjunctionTreeRec(DAG, LHS, OutCC, if (NegateAfterAll)
NegateOpsAndResult, CmpR,
RHSCC);
// If we transformed an OR to and AND then we have to negate the result
// (or absorb the Negate parameter).
if (NegateOpsAndResult && !Negate)
OutCC = AArch64CC::getInvertedCondCode(OutCC); OutCC = AArch64CC::getInvertedCondCode(OutCC);
return CmpL; return CmpL;
} }
/// Emit conjunction or disjunction tree with the CMP/FCMP followed by a chain /// Emit expression as a conjunction (a series of CCMP/CFCMP ops).
/// of CCMP/CFCMP ops. See @ref AArch64CCMP. /// In some cases this is even possible with OR operations in the expression.
/// \see emitConjunctionDisjunctionTreeRec(). /// See \ref AArch64CCMP.
static SDValue emitConjunctionDisjunctionTree(SelectionDAG &DAG, SDValue Val, /// \see emitConjunctionRec().
AArch64CC::CondCode &OutCC) { static SDValue emitConjunction(SelectionDAG &DAG, SDValue Val,
bool CanNegate; AArch64CC::CondCode &OutCC) {
if (!isConjunctionDisjunctionTree(Val, CanNegate)) bool DummyCanNegate;
bool DummyMustBeFirst;
if (!canEmitConjunction(Val, DummyCanNegate, DummyMustBeFirst, false))
return SDValue(); return SDValue();
return emitConjunctionDisjunctionTreeRec(DAG, Val, OutCC, false, SDValue(), return emitConjunctionRec(DAG, Val, OutCC, false, SDValue(), AArch64CC::AL);
AArch64CC::AL);
} }
/// @} /// @}
@ -1859,7 +1891,7 @@ static SDValue getAArch64Cmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
} }
if (!Cmp && (RHSC->isNullValue() || RHSC->isOne())) { if (!Cmp && (RHSC->isNullValue() || RHSC->isOne())) {
if ((Cmp = emitConjunctionDisjunctionTree(DAG, LHS, AArch64CC))) { if ((Cmp = emitConjunction(DAG, LHS, AArch64CC))) {
if ((CC == ISD::SETNE) ^ RHSC->isNullValue()) if ((CC == ISD::SETNE) ^ RHSC->isNullValue())
AArch64CC = AArch64CC::getInvertedCondCode(AArch64CC); AArch64CC = AArch64CC::getInvertedCondCode(AArch64CC);
} }

View File

@ -90,7 +90,6 @@ class UnmangledFuncInfo {
public: public:
using ID = AMDGPULibFunc::EFuncId; using ID = AMDGPULibFunc::EFuncId;
UnmangledFuncInfo() = default;
UnmangledFuncInfo(StringRef _Name, unsigned _NumArgs) UnmangledFuncInfo(StringRef _Name, unsigned _NumArgs)
: Name(_Name), NumArgs(_NumArgs) {} : Name(_Name), NumArgs(_NumArgs) {}
// Get index to Table by function name. // Get index to Table by function name.

View File

@ -25,6 +25,7 @@
#include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h" #include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -568,6 +569,14 @@ bool MipsAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
} }
} }
bool MipsAsmBackend::isMicroMips(const MCSymbol *Sym) const {
if (const auto *ElfSym = dyn_cast<const MCSymbolELF>(Sym)) {
if (ElfSym->getOther() & ELF::STO_MIPS_MICROMIPS)
return true;
}
return false;
}
MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, MCAsmBackend *llvm::createMipsAsmBackend(const Target &T,
const MCSubtargetInfo &STI, const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI, const MCRegisterInfo &MRI,

View File

@ -25,6 +25,7 @@ class MCAssembler;
struct MCFixupKindInfo; struct MCFixupKindInfo;
class MCObjectWriter; class MCObjectWriter;
class MCRegisterInfo; class MCRegisterInfo;
class MCSymbolELF;
class Target; class Target;
class MipsAsmBackend : public MCAsmBackend { class MipsAsmBackend : public MCAsmBackend {
@ -90,6 +91,7 @@ class MipsAsmBackend : public MCAsmBackend {
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target) override; const MCValue &Target) override;
bool isMicroMips(const MCSymbol *Sym) const override;
}; // class MipsAsmBackend }; // class MipsAsmBackend
} // namespace } // namespace

View File

@ -15,6 +15,7 @@
#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbolELF.h"
@ -53,6 +54,22 @@ void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
createPendingLabelRelocs(); createPendingLabelRelocs();
} }
void MipsELFStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
Frame.Begin = getContext().createTempSymbol();
MCELFStreamer::EmitLabel(Frame.Begin);
}
MCSymbol *MipsELFStreamer::EmitCFILabel() {
MCSymbol *Label = getContext().createTempSymbol("cfi", true);
MCELFStreamer::EmitLabel(Label);
return Label;
}
void MipsELFStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
Frame.End = getContext().createTempSymbol();
MCELFStreamer::EmitLabel(Frame.End);
}
void MipsELFStreamer::createPendingLabelRelocs() { void MipsELFStreamer::createPendingLabelRelocs() {
MipsTargetELFStreamer *ELFTargetStreamer = MipsTargetELFStreamer *ELFTargetStreamer =
static_cast<MipsTargetELFStreamer *>(getTargetStreamer()); static_cast<MipsTargetELFStreamer *>(getTargetStreamer());

View File

@ -26,6 +26,7 @@ class MCAsmBackend;
class MCCodeEmitter; class MCCodeEmitter;
class MCContext; class MCContext;
class MCSubtargetInfo; class MCSubtargetInfo;
struct MCDwarfFrameInfo;
class MipsELFStreamer : public MCELFStreamer { class MipsELFStreamer : public MCELFStreamer {
SmallVector<std::unique_ptr<MipsOptionRecord>, 8> MipsOptionRecords; SmallVector<std::unique_ptr<MipsOptionRecord>, 8> MipsOptionRecords;
@ -60,6 +61,12 @@ class MipsELFStreamer : public MCELFStreamer {
void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override;
void EmitIntValue(uint64_t Value, unsigned Size) override; void EmitIntValue(uint64_t Value, unsigned Size) override;
// Overriding these functions allows us to avoid recording of these labels
// in EmitLabel and later marking them as microMIPS.
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
MCSymbol *EmitCFILabel() override;
/// Emits all the option records stored up until the point it's called. /// Emits all the option records stored up until the point it's called.
void EmitMipsOptionRecords(); void EmitMipsOptionRecords();

View File

@ -1733,7 +1733,7 @@ defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6;
defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6;
def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6;
def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1 ZERO))>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6;
def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src),
(TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6;

View File

@ -838,7 +838,7 @@ def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))),
(SUBu GPR32:$src, GPR32:$src2), sub_32)>; (SUBu GPR32:$src, GPR32:$src2), sub_32)>;
def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
(MUL GPR32:$src, GPR32:$src2), sub_32)>; (MUL GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS3_NOT_32R6_64R6;
def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))), def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
(PseudoMFHI ACC64:$src), sub_32)>; (PseudoMFHI ACC64:$src), sub_32)>;
@ -1139,3 +1139,6 @@ def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs),
"sltu\t$rs, $rt, $imm">, GPR_64; "sltu\t$rs, $rt, $imm">, GPR_64;
def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs, def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
imm64:$imm)>, GPR_64; imm64:$imm)>, GPR_64;
def : MipsInstAlias<"rdhwr $rt, $rs",
(RDHWR64 GPR64Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, GPR_64;

View File

@ -301,6 +301,9 @@ def : MipsPat<(select (i32 (seteq i32:$cond, immz)), immz, i64:$f),
// Patterns used for matching away redundant sign extensions. // Patterns used for matching away redundant sign extensions.
// MIPS32 arithmetic instructions sign extend their result implicitly. // MIPS32 arithmetic instructions sign extend their result implicitly.
def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)),
(MUL_R6 GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6;
def : MipsPat<(i64 (sext (i32 (sdiv GPR32:$src, GPR32:$src2)))), def : MipsPat<(i64 (sext (i32 (sdiv GPR32:$src, GPR32:$src2)))),
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
(DIV GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; (DIV GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6;

View File

@ -953,6 +953,11 @@ bool MipsFastISel::selectBranch(const Instruction *I) {
MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
// For now, just try the simplest case where it's fed by a compare. // For now, just try the simplest case where it's fed by a compare.
if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
MVT CIMVT =
TLI.getValueType(DL, CI->getOperand(0)->getType(), true).getSimpleVT();
if (CIMVT == MVT::i1)
return false;
unsigned CondReg = getRegForValue(CI); unsigned CondReg = getRegForValue(CI);
BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
.addReg(CondReg) .addReg(CondReg)

View File

@ -485,14 +485,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
def CTC1 : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, MFC1_FM<6>, def CTC1 : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, MFC1_FM<6>,
ISA_MIPS1; ISA_MIPS1;
def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, def MFC1 : MMRel, StdMMR6Rel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1,
bitconvert>, MFC1_FM<0>, ISA_MIPS1; bitconvert>, MFC1_FM<0>, ISA_MIPS1;
def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>, def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>,
ISA_MIPS1, FGR_64 { ISA_MIPS1, FGR_64 {
let DecoderNamespace = "MipsFP64"; let DecoderNamespace = "MipsFP64";
} }
def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, def MTC1 : MMRel, StdMMR6Rel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1,
bitconvert>, MFC1_FM<4>, ISA_MIPS1; bitconvert>, MFC1_FM<4>, ISA_MIPS1;
def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>, def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>,
ISA_MIPS1, FGR_64 { ISA_MIPS1, FGR_64 {
let DecoderNamespace = "MipsFP64"; let DecoderNamespace = "MipsFP64";

View File

@ -299,8 +299,12 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
// register). Unfortunately, we have to make this decision before register // register). Unfortunately, we have to make this decision before register
// allocation so for now we use a spill/reload sequence for all // allocation so for now we use a spill/reload sequence for all
// double-precision values in regardless of being an odd/even register. // double-precision values in regardless of being an odd/even register.
if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || //
(FP64 && !Subtarget.useOddSPReg())) { // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
// implicit operand, so other passes (like ShrinkWrapping) are aware that
// stack is used.
if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
&& I->getOperand(3).getReg() == Mips::SP) {
unsigned DstReg = I->getOperand(0).getReg(); unsigned DstReg = I->getOperand(0).getReg();
unsigned LoReg = I->getOperand(1).getReg(); unsigned LoReg = I->getOperand(1).getReg();
unsigned HiReg = I->getOperand(2).getReg(); unsigned HiReg = I->getOperand(2).getReg();
@ -360,9 +364,12 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
// register). Unfortunately, we have to make this decision before register // register). Unfortunately, we have to make this decision before register
// allocation so for now we use a spill/reload sequence for all // allocation so for now we use a spill/reload sequence for all
// double-precision values in regardless of being an odd/even register. // double-precision values in regardless of being an odd/even register.
//
if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
(FP64 && !Subtarget.useOddSPReg())) { // implicit operand, so other passes (like ShrinkWrapping) are aware that
// stack is used.
if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
&& I->getOperand(3).getReg() == Mips::SP) {
unsigned DstReg = I->getOperand(0).getReg(); unsigned DstReg = I->getOperand(0).getReg();
unsigned SrcReg = Op1.getReg(); unsigned SrcReg = Op1.getReg();
unsigned N = Op2.getImm(); unsigned N = Op2.getImm();

View File

@ -238,6 +238,18 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
case Mips::WRDSP: case Mips::WRDSP:
addDSPCtrlRegOperands(true, MI, MF); addDSPCtrlRegOperands(true, MI, MF);
break; break;
case Mips::BuildPairF64_64:
case Mips::ExtractElementF64_64:
if (!Subtarget->useOddSPReg()) {
MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true));
break;
}
// fallthrough
case Mips::BuildPairF64:
case Mips::ExtractElementF64:
if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1())
MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true));
break;
default: default:
replaceUsesWithZeroReg(MRI, MI); replaceUsesWithZeroReg(MRI, MI);
} }

View File

@ -25,9 +25,14 @@
using namespace llvm; using namespace llvm;
static unsigned getUnconditionalBranch(const MipsSubtarget &STI) {
if (STI.inMicroMipsMode())
return STI.isPositionIndependent() ? Mips::B_MM : Mips::J_MM;
return STI.isPositionIndependent() ? Mips::B : Mips::J;
}
MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI)
: MipsInstrInfo(STI, STI.isPositionIndependent() ? Mips::B : Mips::J), : MipsInstrInfo(STI, getUnconditionalBranch(STI)), RI() {}
RI() {}
const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const {
return RI; return RI;
@ -643,7 +648,7 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 ||
Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T ||
Opc == Mips::BC1F || Opc == Mips::B || Opc == Mips::J || Opc == Mips::BC1F || Opc == Mips::B || Opc == Mips::J ||
Opc == Mips::B_MM || Opc == Mips::BEQZC_MM || Opc == Mips::J_MM || Opc == Mips::B_MM || Opc == Mips::BEQZC_MM ||
Opc == Mips::BNEZC_MM || Opc == Mips::BEQC || Opc == Mips::BNEC || Opc == Mips::BNEZC_MM || Opc == Mips::BEQC || Opc == Mips::BNEC ||
Opc == Mips::BLTC || Opc == Mips::BGEC || Opc == Mips::BLTUC || Opc == Mips::BLTC || Opc == Mips::BGEC || Opc == Mips::BLTUC ||
Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC || Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC ||

View File

@ -592,6 +592,7 @@ def : InstRW<[P9_PM_3C, IP_EXECO_1C, IP_EXECE_1C, DISP_1C, DISP_1C, DISP_1C],
XXPERM, XXPERM,
XXPERMR, XXPERMR,
XXSLDWI, XXSLDWI,
XXSLDWIs,
XXSPLTIB, XXSPLTIB,
XXSPLTW, XXSPLTW,
XXSPLTWs, XXSPLTWs,

View File

@ -8454,17 +8454,6 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
if (V2.isUndef() && PPC::isSplatShuffleMask(SVOp, 4)) { if (V2.isUndef() && PPC::isSplatShuffleMask(SVOp, 4)) {
int SplatIdx = PPC::getVSPLTImmediate(SVOp, 4, DAG); int SplatIdx = PPC::getVSPLTImmediate(SVOp, 4, DAG);
// If the source for the shuffle is a scalar_to_vector that came from a
// 32-bit load, it will have used LXVWSX so we don't need to splat again.
if (Subtarget.hasP9Vector() &&
((isLittleEndian && SplatIdx == 3) ||
(!isLittleEndian && SplatIdx == 0))) {
SDValue Src = V1.getOperand(0);
if (Src.getOpcode() == ISD::SCALAR_TO_VECTOR &&
Src.getOperand(0).getOpcode() == ISD::LOAD &&
Src.getOperand(0).hasOneUse())
return V1;
}
SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, V1); SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, V1);
SDValue Splat = DAG.getNode(PPCISD::XXSPLT, dl, MVT::v4i32, Conv, SDValue Splat = DAG.getNode(PPCISD::XXSPLT, dl, MVT::v4i32, Conv,
DAG.getConstant(SplatIdx, dl, MVT::i32)); DAG.getConstant(SplatIdx, dl, MVT::i32));

View File

@ -877,6 +877,12 @@ let Uses = [RM] in {
"xxsldwi $XT, $XA, $XB, $SHW", IIC_VecPerm, "xxsldwi $XT, $XA, $XB, $SHW", IIC_VecPerm,
[(set v4i32:$XT, (PPCvecshl v4i32:$XA, v4i32:$XB, [(set v4i32:$XT, (PPCvecshl v4i32:$XA, v4i32:$XB,
imm32SExt16:$SHW))]>; imm32SExt16:$SHW))]>;
let isCodeGenOnly = 1 in
def XXSLDWIs : XX3Form_2s<60, 2,
(outs vsrc:$XT), (ins vsfrc:$XA, u2imm:$SHW),
"xxsldwi $XT, $XA, $XA, $SHW", IIC_VecPerm, []>;
def XXSPLTW : XX2Form_2<60, 164, def XXSPLTW : XX2Form_2<60, 164,
(outs vsrc:$XT), (ins vsrc:$XB, u2imm:$UIM), (outs vsrc:$XT), (ins vsrc:$XB, u2imm:$UIM),
"xxspltw $XT, $XB, $UIM", IIC_VecPerm, "xxspltw $XT, $XB, $UIM", IIC_VecPerm,
@ -886,6 +892,7 @@ let Uses = [RM] in {
def XXSPLTWs : XX2Form_2<60, 164, def XXSPLTWs : XX2Form_2<60, 164,
(outs vsrc:$XT), (ins vfrc:$XB, u2imm:$UIM), (outs vsrc:$XT), (ins vfrc:$XB, u2imm:$UIM),
"xxspltw $XT, $XB, $UIM", IIC_VecPerm, []>; "xxspltw $XT, $XB, $UIM", IIC_VecPerm, []>;
} // hasSideEffects } // hasSideEffects
} // UseVSXReg = 1 } // UseVSXReg = 1
@ -1466,8 +1473,6 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns.
(f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))), (f64 (PPCmtvsra (i64 (vector_extract v2i64:$S, 1)))))),
(f32 (XSCVUXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>; (f32 (XSCVUXDSP (COPY_TO_REGCLASS (XXPERMDI $S, $S, 2), VSFRC)))>;
} }
def : Pat<(v4i32 (scalar_to_vector ScalarLoads.Li32)),
(v4i32 (XXSPLTWs (LIWAX xoaddr:$src), 1))>;
// Instructions for converting float to i64 feeding a store. // Instructions for converting float to i64 feeding a store.
let Predicates = [NoP9Vector] in { let Predicates = [NoP9Vector] in {
@ -3050,13 +3055,47 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in {
(STXVX $rS, xoaddr:$dst)>; (STXVX $rS, xoaddr:$dst)>;
def : Pat<(int_ppc_vsx_stxvd2x v2f64:$rS, xoaddr:$dst), def : Pat<(int_ppc_vsx_stxvd2x v2f64:$rS, xoaddr:$dst),
(STXVX $rS, xoaddr:$dst)>; (STXVX $rS, xoaddr:$dst)>;
def : Pat<(v4i32 (scalar_to_vector (i32 (load xoaddr:$src)))),
(v4i32 (LXVWSX xoaddr:$src))>; let AddedComplexity = 400 in {
def : Pat<(v4f32 (scalar_to_vector (f32 (load xoaddr:$src)))), // LIWAX - This instruction is used for sign extending i32 -> i64.
(v4f32 (LXVWSX xoaddr:$src))>; // LIWZX - This instruction will be emitted for i32, f32, and when
def : Pat<(v4f32 (scalar_to_vector // zero-extending i32 to i64 (zext i32 -> i64).
(f32 (fpround (f64 (extloadf32 xoaddr:$src)))))), let Predicates = [IsLittleEndian] in {
(v4f32 (LXVWSX xoaddr:$src))>;
def : Pat<(v2i64 (scalar_to_vector (i64 (sextloadi32 xoaddr:$src)))),
(v2i64 (XXPERMDIs
(COPY_TO_REGCLASS (LIWAX xoaddr:$src), VSRC), 2))>;
def : Pat<(v2i64 (scalar_to_vector (i64 (zextloadi32 xoaddr:$src)))),
(v2i64 (XXPERMDIs
(COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC), 2))>;
def : Pat<(v4i32 (scalar_to_vector (i32 (load xoaddr:$src)))),
(v4i32 (XXPERMDIs
(COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC), 2))>;
def : Pat<(v4f32 (scalar_to_vector (f32 (load xoaddr:$src)))),
(v4f32 (XXPERMDIs
(COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC), 2))>;
}
let Predicates = [IsBigEndian] in {
def : Pat<(v2i64 (scalar_to_vector (i64 (sextloadi32 xoaddr:$src)))),
(v2i64 (COPY_TO_REGCLASS (LIWAX xoaddr:$src), VSRC))>;
def : Pat<(v2i64 (scalar_to_vector (i64 (zextloadi32 xoaddr:$src)))),
(v2i64 (COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC))>;
def : Pat<(v4i32 (scalar_to_vector (i32 (load xoaddr:$src)))),
(v4i32 (XXSLDWIs
(COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC), 1))>;
def : Pat<(v4f32 (scalar_to_vector (f32 (load xoaddr:$src)))),
(v4f32 (XXSLDWIs
(COPY_TO_REGCLASS (LIWZX xoaddr:$src), VSRC), 1))>;
}
}
// Build vectors from i8 loads // Build vectors from i8 loads
def : Pat<(v16i8 (scalar_to_vector ScalarLoads.Li8)), def : Pat<(v16i8 (scalar_to_vector ScalarLoads.Li8)),
@ -3218,6 +3257,39 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in {
def : Pat<(f32 (fpround (f64 (extloadf32 ixaddr:$src)))), def : Pat<(f32 (fpround (f64 (extloadf32 ixaddr:$src)))),
(f32 (DFLOADf32 ixaddr:$src))>; (f32 (DFLOADf32 ixaddr:$src))>;
let AddedComplexity = 400 in {
// The following pseudoinstructions are used to ensure the utilization
// of all 64 VSX registers.
let Predicates = [IsLittleEndian, HasP9Vector] in {
def : Pat<(v2i64 (scalar_to_vector (i64 (load ixaddr:$src)))),
(v2i64 (XXPERMDIs
(COPY_TO_REGCLASS (DFLOADf64 ixaddr:$src), VSRC), 2))>;
def : Pat<(v2i64 (scalar_to_vector (i64 (load xaddr:$src)))),
(v2i64 (XXPERMDIs
(COPY_TO_REGCLASS (XFLOADf64 xaddr:$src), VSRC), 2))>;
def : Pat<(v2f64 (scalar_to_vector (f64 (load ixaddr:$src)))),
(v2f64 (XXPERMDIs
(COPY_TO_REGCLASS (DFLOADf64 ixaddr:$src), VSRC), 2))>;
def : Pat<(v2f64 (scalar_to_vector (f64 (load xaddr:$src)))),
(v2f64 (XXPERMDIs
(COPY_TO_REGCLASS (XFLOADf64 xaddr:$src), VSRC), 2))>;
}
let Predicates = [IsBigEndian, HasP9Vector] in {
def : Pat<(v2i64 (scalar_to_vector (i64 (load ixaddr:$src)))),
(v2i64 (COPY_TO_REGCLASS (DFLOADf64 ixaddr:$src), VSRC))>;
def : Pat<(v2i64 (scalar_to_vector (i64 (load xaddr:$src)))),
(v2i64 (COPY_TO_REGCLASS (XFLOADf64 xaddr:$src), VSRC))>;
def : Pat<(v2f64 (scalar_to_vector (f64 (load ixaddr:$src)))),
(v2f64 (COPY_TO_REGCLASS (DFLOADf64 ixaddr:$src), VSRC))>;
def : Pat<(v2f64 (scalar_to_vector (f64 (load xaddr:$src)))),
(v2f64 (COPY_TO_REGCLASS (XFLOADf64 xaddr:$src), VSRC))>;
}
}
let Predicates = [IsBigEndian, HasP9Vector] in { let Predicates = [IsBigEndian, HasP9Vector] in {
// (Un)Signed DWord vector extract -> QP // (Un)Signed DWord vector extract -> QP
@ -3932,3 +4004,4 @@ let AddedComplexity = 400 in {
(v4i32 (VEXTSH2W $A))>; (v4i32 (VEXTSH2W $A))>;
} }
} }

View File

@ -2924,12 +2924,20 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I,
// x & (-1 >> y) s>= x -> x s<= (-1 >> y) // x & (-1 >> y) s>= x -> x s<= (-1 >> y)
if (X != I.getOperand(1)) // X must be on RHS of comparison! if (X != I.getOperand(1)) // X must be on RHS of comparison!
return nullptr; // Ignore the other case. return nullptr; // Ignore the other case.
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
return nullptr;
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
return nullptr;
DstPred = ICmpInst::Predicate::ICMP_SLE; DstPred = ICmpInst::Predicate::ICMP_SLE;
break; break;
case ICmpInst::Predicate::ICMP_SLT: case ICmpInst::Predicate::ICMP_SLT:
// x & (-1 >> y) s< x -> x s> (-1 >> y) // x & (-1 >> y) s< x -> x s> (-1 >> y)
if (X != I.getOperand(1)) // X must be on RHS of comparison! if (X != I.getOperand(1)) // X must be on RHS of comparison!
return nullptr; // Ignore the other case. return nullptr; // Ignore the other case.
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
return nullptr;
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
return nullptr;
DstPred = ICmpInst::Predicate::ICMP_SGT; DstPred = ICmpInst::Predicate::ICMP_SGT;
break; break;
case ICmpInst::Predicate::ICMP_SLE: case ICmpInst::Predicate::ICMP_SLE:

View File

@ -231,17 +231,17 @@ struct TransformedFunction {
TransformedFunction& operator=(TransformedFunction&&) = default; TransformedFunction& operator=(TransformedFunction&&) = default;
/// Type of the function before the transformation. /// Type of the function before the transformation.
FunctionType* const OriginalType; FunctionType *OriginalType;
/// Type of the function after the transformation. /// Type of the function after the transformation.
FunctionType* const TransformedType; FunctionType *TransformedType;
/// Transforming a function may change the position of arguments. This /// Transforming a function may change the position of arguments. This
/// member records the mapping from each argument's old position to its new /// member records the mapping from each argument's old position to its new
/// position. Argument positions are zero-indexed. If the transformation /// position. Argument positions are zero-indexed. If the transformation
/// from F to F' made the first argument of F into the third argument of F', /// from F to F' made the first argument of F into the third argument of F',
/// then ArgumentIndexMapping[0] will equal 2. /// then ArgumentIndexMapping[0] will equal 2.
const std::vector<unsigned> ArgumentIndexMapping; std::vector<unsigned> ArgumentIndexMapping;
}; };
/// Given function attributes from a call site for the original function, /// Given function attributes from a call site for the original function,

View File

@ -41,6 +41,7 @@
#include "llvm/IR/Dominators.h" #include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PredIteratorCache.h" #include "llvm/IR/PredIteratorCache.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils.h"
@ -201,6 +202,21 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
SSAUpdate.RewriteUse(*UseToRewrite); SSAUpdate.RewriteUse(*UseToRewrite);
} }
SmallVector<DbgValueInst *, 4> DbgValues;
llvm::findDbgValues(DbgValues, I);
// Update pre-existing debug value uses that reside outside the loop.
auto &Ctx = I->getContext();
for (auto DVI : DbgValues) {
BasicBlock *UserBB = DVI->getParent();
if (InstBB == UserBB || L->contains(UserBB))
continue;
// We currently only handle debug values residing in blocks where we have
// inserted a PHI instruction.
if (Value *V = SSAUpdate.FindValueForBlock(UserBB))
DVI->setOperand(0, MetadataAsValue::get(Ctx, ValueAsMetadata::get(V)));
}
// SSAUpdater might have inserted phi-nodes inside other loops. We'll need // SSAUpdater might have inserted phi-nodes inside other loops. We'll need
// to post-process them to keep LCSSA form. // to post-process them to keep LCSSA form.
for (PHINode *InsertedPN : InsertedPHIs) { for (PHINode *InsertedPN : InsertedPHIs) {

View File

@ -64,6 +64,11 @@ bool SSAUpdater::HasValueForBlock(BasicBlock *BB) const {
return getAvailableVals(AV).count(BB); return getAvailableVals(AV).count(BB);
} }
Value *SSAUpdater::FindValueForBlock(BasicBlock *BB) const {
AvailableValsTy::iterator AVI = getAvailableVals(AV).find(BB);
return (AVI != getAvailableVals(AV).end()) ? AVI->second : nullptr;
}
void SSAUpdater::AddAvailableValue(BasicBlock *BB, Value *V) { void SSAUpdater::AddAvailableValue(BasicBlock *BB, Value *V) {
assert(ProtoType && "Need to initialize SSAUpdater"); assert(ProtoType && "Need to initialize SSAUpdater");
assert(ProtoType == V->getType() && assert(ProtoType == V->getType() &&

View File

@ -1216,7 +1216,6 @@ class DeclContextLookupResult {
value_type SingleElement; value_type SingleElement;
public: public:
iterator() = default;
explicit iterator(pointer Pos, value_type Single = nullptr) explicit iterator(pointer Pos, value_type Single = nullptr)
: IteratorBase(Pos), SingleElement(Single) {} : IteratorBase(Pos), SingleElement(Single) {}

View File

@ -1953,6 +1953,39 @@ def Target : InheritableAttr {
return parse(getFeaturesStr()); return parse(getFeaturesStr());
} }
StringRef getArchitecture() const {
StringRef Features = getFeaturesStr();
if (Features == "default") return {};
SmallVector<StringRef, 1> AttrFeatures;
Features.split(AttrFeatures, ",");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
if (Feature.startswith("arch="))
return Feature.drop_front(sizeof("arch=") - 1);
}
return "";
}
// Gets the list of features as simple string-refs with no +/- or 'no-'.
// Only adds the items to 'Out' that are additions.
void getAddedFeatures(llvm::SmallVectorImpl<StringRef> &Out) const {
StringRef Features = getFeaturesStr();
if (Features == "default") return;
SmallVector<StringRef, 1> AttrFeatures;
Features.split(AttrFeatures, ",");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
if (!Feature.startswith("no-") && !Feature.startswith("arch=") &&
!Feature.startswith("fpmath=") && !Feature.startswith("tune="))
Out.push_back(Feature);
}
}
template<class Compare> template<class Compare>
ParsedTargetAttr parse(Compare cmp) const { ParsedTargetAttr parse(Compare cmp) const {
ParsedTargetAttr Attrs = parse(); ParsedTargetAttr Attrs = parse();

View File

@ -3364,7 +3364,7 @@ def IFuncDocs : Documentation {
let Content = [{ let Content = [{
``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function. ``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function.
The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should take no arguments and return a pointer. The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should return a pointer.
The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline.

View File

@ -238,7 +238,7 @@ def warn_option_invalid_ocl_version : Warning<
"OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>; "OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>;
def warn_stdlibcxx_not_found : Warning< def warn_stdlibcxx_not_found : Warning<
"include path for stdlibc++ headers not found; pass '-std=libc++' on the " "include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the "
"command line to use the libc++ standard library instead">, "command line to use the libc++ standard library instead">,
InGroup<DiagGroup<"stdlibcxx-not-found">>; InGroup<DiagGroup<"stdlibcxx-not-found">>;
} }

View File

@ -2857,8 +2857,6 @@ def err_cyclic_alias : Error<
"%select{alias|ifunc}0 definition is part of a cycle">; "%select{alias|ifunc}0 definition is part of a cycle">;
def err_ifunc_resolver_return : Error< def err_ifunc_resolver_return : Error<
"ifunc resolver function must return a pointer">; "ifunc resolver function must return a pointer">;
def err_ifunc_resolver_params : Error<
"ifunc resolver function must have no parameters">;
def warn_attribute_wrong_decl_type_str : Warning< def warn_attribute_wrong_decl_type_str : Warning<
"%0 attribute only applies to %1">, InGroup<IgnoredAttributes>; "%0 attribute only applies to %1">, InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type_str : Error< def err_attribute_wrong_decl_type_str : Error<

View File

@ -9734,6 +9734,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true; return true;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Multiversioned functions always have to be emitted, because they are used
// by the resolver.
if (FD->isMultiVersion())
return true;
// Forward declarations aren't required. // Forward declarations aren't required.
if (!FD->doesThisDeclarationHaveABody()) if (!FD->doesThisDeclarationHaveABody())
return FD->doesDeclarationForceExternallyVisibleDefinition(); return FD->doesDeclarationForceExternallyVisibleDefinition();

View File

@ -725,7 +725,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// If we're paying attention to global visibility, apply // If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method. // -finline-visibility-hidden if this is an inline method.
if (useInlineVisibilityHidden(D)) if (useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true); LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
} }
} }
@ -915,7 +915,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
// Note that we do this before merging information about // Note that we do this before merging information about
// the class visibility. // the class visibility.
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D)) if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true); LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
} }
// If this class member has an explicit visibility attribute, the only // If this class member has an explicit visibility attribute, the only
@ -1262,7 +1262,27 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
!isTemplateInstantiation(FD->getTemplateSpecializationKind())) !isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none(); return LinkageInfo::none();
// If a function is hidden by -fvisibility-inlines-hidden option and
// is not explicitly attributed as a hidden function,
// we should not make static local variables in the function hidden.
LV = getLVForDecl(FD, computation); LV = getLVForDecl(FD, computation);
if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
!LV.isVisibilityExplicit()) {
assert(cast<VarDecl>(D)->isStaticLocal());
// If this was an implicitly hidden inline method, check again for
// explicit visibility on the parent class, and use that for static locals
// if present.
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
LV = getLVForDecl(MD->getParent(), computation);
if (!LV.isVisibilityExplicit()) {
Visibility globalVisibility =
computation.isValueVisibility()
? Context.getLangOpts().getValueVisibilityMode()
: Context.getLangOpts().getTypeVisibilityMode();
return LinkageInfo(VisibleNoLinkage, globalVisibility,
/*visibilityExplicit=*/false);
}
}
} }
if (!isExternallyVisible(LV.getLinkage())) if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none(); return LinkageInfo::none();

View File

@ -2359,91 +2359,53 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
CGM.getSanStats().create(IRB, SSK); CGM.getSanStats().create(IRB, SSK);
} }
llvm::Value *CodeGenFunction::FormResolverCondition( llvm::Value *
const TargetMultiVersionResolverOption &RO) { CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) {
llvm::Value *TrueCondition = nullptr; llvm::Value *Condition = nullptr;
if (!RO.ParsedAttribute.Architecture.empty())
TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture);
if (!RO.ParsedAttribute.Features.empty()) { if (!RO.Conditions.Architecture.empty())
SmallVector<StringRef, 8> FeatureList; Condition = EmitX86CpuIs(RO.Conditions.Architecture);
llvm::for_each(RO.ParsedAttribute.Features,
[&FeatureList](const std::string &Feature) { if (!RO.Conditions.Features.empty()) {
FeatureList.push_back(StringRef{Feature}.substr(1)); llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features);
}); Condition =
llvm::Value *FeatureCmp = EmitX86CpuSupports(FeatureList); Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond;
TrueCondition = TrueCondition ? Builder.CreateAnd(TrueCondition, FeatureCmp)
: FeatureCmp;
} }
return TrueCondition; return Condition;
} }
void CodeGenFunction::EmitTargetMultiVersionResolver( void CodeGenFunction::EmitMultiVersionResolver(
llvm::Function *Resolver, llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
ArrayRef<TargetMultiVersionResolverOption> Options) {
assert((getContext().getTargetInfo().getTriple().getArch() == assert((getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86 || llvm::Triple::x86 ||
getContext().getTargetInfo().getTriple().getArch() == getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) && llvm::Triple::x86_64) &&
"Only implemented for x86 targets"); "Only implemented for x86 targets");
// Main function's basic block.
llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver);
Builder.SetInsertPoint(CurBlock);
EmitX86CpuInit();
llvm::Function *DefaultFunc = nullptr;
for (const TargetMultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock);
llvm::Value *TrueCondition = FormResolverCondition(RO);
if (!TrueCondition) {
DefaultFunc = RO.Function;
} else {
llvm::BasicBlock *RetBlock = createBasicBlock("ro_ret", Resolver);
llvm::IRBuilder<> RetBuilder(RetBlock);
RetBuilder.CreateRet(RO.Function);
CurBlock = createBasicBlock("ro_else", Resolver);
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
}
}
assert(DefaultFunc && "No default version?");
// Emit return from the 'else-ist' block.
Builder.SetInsertPoint(CurBlock);
Builder.CreateRet(DefaultFunc);
}
void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
llvm::Function *Resolver,
ArrayRef<CPUDispatchMultiVersionResolverOption> Options) {
assert((getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86 ||
getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) &&
"Only implemented for x86 targets");
// Main function's basic block. // Main function's basic block.
llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
Builder.SetInsertPoint(CurBlock); Builder.SetInsertPoint(CurBlock);
EmitX86CpuInit(); EmitX86CpuInit();
for (const CPUDispatchMultiVersionResolverOption &RO : Options) { for (const MultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock); Builder.SetInsertPoint(CurBlock);
llvm::Value *Condition = FormResolverCondition(RO);
// "generic" case should catch-all. // The 'default' or 'generic' case.
if (RO.FeatureMask == 0) { if (!Condition) {
assert(&RO == Options.end() - 1 &&
"Default or Generic case must be last");
Builder.CreateRet(RO.Function); Builder.CreateRet(RO.Function);
return; return;
} }
llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver); llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
llvm::IRBuilder<> RetBuilder(RetBlock); llvm::IRBuilder<> RetBuilder(RetBlock);
RetBuilder.CreateRet(RO.Function); RetBuilder.CreateRet(RO.Function);
CurBlock = createBasicBlock("resolver_else", Resolver); CurBlock = createBasicBlock("resolver_else", Resolver);
llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask); Builder.CreateCondBr(Condition, RetBlock, CurBlock);
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
} }
// If no generic/default, emit an unreachable.
Builder.SetInsertPoint(CurBlock); Builder.SetInsertPoint(CurBlock);
llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
TrapCall->setDoesNotReturn(); TrapCall->setDoesNotReturn();

View File

@ -4247,30 +4247,26 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK); void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
struct TargetMultiVersionResolverOption { struct MultiVersionResolverOption {
llvm::Function *Function; llvm::Function *Function;
TargetAttr::ParsedTargetAttr ParsedAttribute; struct Conds {
unsigned Priority; StringRef Architecture;
TargetMultiVersionResolverOption( llvm::SmallVector<StringRef, 8> Features;
const TargetInfo &TargInfo, llvm::Function *F,
const clang::TargetAttr::ParsedTargetAttr &PT)
: Function(F), ParsedAttribute(PT), Priority(0u) {
for (StringRef Feat : PT.Features)
Priority = std::max(Priority,
TargInfo.multiVersionSortPriority(Feat.substr(1)));
if (!PT.Architecture.empty()) Conds(StringRef Arch, ArrayRef<StringRef> Feats)
Priority = std::max(Priority, : Architecture(Arch), Features(Feats.begin(), Feats.end()) {}
TargInfo.multiVersionSortPriority(PT.Architecture)); } Conditions;
}
bool operator>(const TargetMultiVersionResolverOption &Other) const { MultiVersionResolverOption(llvm::Function *F, StringRef Arch,
return Priority > Other.Priority; ArrayRef<StringRef> Feats)
} : Function(F), Conditions(Arch, Feats) {}
}; };
void EmitTargetMultiVersionResolver(
llvm::Function *Resolver, // Emits the body of a multiversion function's resolver. Assumes that the
ArrayRef<TargetMultiVersionResolverOption> Options); // options are already sorted in the proper order, with the 'default' option
// last (if it exists).
void EmitMultiVersionResolver(llvm::Function *Resolver,
ArrayRef<MultiVersionResolverOption> Options);
struct CPUDispatchMultiVersionResolverOption { struct CPUDispatchMultiVersionResolverOption {
llvm::Function *Function; llvm::Function *Function;
@ -4306,8 +4302,7 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs); llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
llvm::Value *EmitX86CpuSupports(uint32_t Mask); llvm::Value *EmitX86CpuSupports(uint32_t Mask);
llvm::Value *EmitX86CpuInit(); llvm::Value *EmitX86CpuInit();
llvm::Value * llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
FormResolverCondition(const TargetMultiVersionResolverOption &RO);
}; };
inline DominatingLLVMValue::saved_type inline DominatingLLVMValue::saved_type

View File

@ -2399,9 +2399,22 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
llvm::Function *NewFn); llvm::Function *NewFn);
static unsigned
TargetMVPriority(const TargetInfo &TI,
const CodeGenFunction::MultiVersionResolverOption &RO) {
unsigned Priority = 0;
for (StringRef Feat : RO.Conditions.Features)
Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
if (!RO.Conditions.Architecture.empty())
Priority = std::max(
Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
return Priority;
}
void CodeGenModule::emitMultiVersionFunctions() { void CodeGenModule::emitMultiVersionFunctions() {
for (GlobalDecl GD : MultiVersionFuncs) { for (GlobalDecl GD : MultiVersionFuncs) {
SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 10> Options; SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
getContext().forEachMultiversionedFunctionVersion( getContext().forEachMultiversionedFunctionVersion(
FD, [this, &GD, &Options](const FunctionDecl *CurFD) { FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
@ -2422,8 +2435,13 @@ void CodeGenModule::emitMultiVersionFunctions() {
} }
assert(Func && "This should have just been created"); assert(Func && "This should have just been created");
} }
Options.emplace_back(getTarget(), cast<llvm::Function>(Func),
CurFD->getAttr<TargetAttr>()->parse()); const auto *TA = CurFD->getAttr<TargetAttr>();
llvm::SmallVector<StringRef, 8> Feats;
TA->getAddedFeatures(Feats);
Options.emplace_back(cast<llvm::Function>(Func),
TA->getArchitecture(), Feats);
}); });
llvm::Function *ResolverFunc = cast<llvm::Function>( llvm::Function *ResolverFunc = cast<llvm::Function>(
@ -2431,11 +2449,16 @@ void CodeGenModule::emitMultiVersionFunctions() {
if (supportsCOMDAT()) if (supportsCOMDAT())
ResolverFunc->setComdat( ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName())); getModule().getOrInsertComdat(ResolverFunc->getName()));
const TargetInfo &TI = getTarget();
std::stable_sort( std::stable_sort(
Options.begin(), Options.end(), Options.begin(), Options.end(),
std::greater<CodeGenFunction::TargetMultiVersionResolverOption>()); [&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
});
CodeGenFunction CGF(*this); CodeGenFunction CGF(*this);
CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options); CGF.EmitMultiVersionResolver(ResolverFunc, Options);
} }
} }
@ -2444,7 +2467,13 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
assert(FD && "Not a FunctionDecl?"); assert(FD && "Not a FunctionDecl?");
const auto *DD = FD->getAttr<CPUDispatchAttr>(); const auto *DD = FD->getAttr<CPUDispatchAttr>();
assert(DD && "Not a cpu_dispatch Function?"); assert(DD && "Not a cpu_dispatch Function?");
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType()); QualType CanonTy = Context.getCanonicalType(FD->getType());
llvm::Type *DeclTy = getTypes().ConvertFunctionType(CanonTy, FD);
if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD);
DeclTy = getTypes().GetFunctionType(FInfo);
}
StringRef ResolverName = getMangledName(GD); StringRef ResolverName = getMangledName(GD);
llvm::Type *ResolverType = llvm::FunctionType::get( llvm::Type *ResolverType = llvm::FunctionType::get(
@ -2455,15 +2484,14 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
/*ForVTable=*/false)); /*ForVTable=*/false));
SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10> SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
Options;
const TargetInfo &Target = getTarget(); const TargetInfo &Target = getTarget();
for (const IdentifierInfo *II : DD->cpus()) { for (const IdentifierInfo *II : DD->cpus()) {
// Get the name of the target function so we can look it up/create it. // Get the name of the target function so we can look it up/create it.
std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + std::string MangledName = getMangledNameImpl(*this, GD, FD, true) +
getCPUSpecificMangling(*this, II->getName()); getCPUSpecificMangling(*this, II->getName());
llvm::Constant *Func = GetOrCreateLLVMFunction( llvm::Constant *Func = GetOrCreateLLVMFunction(
MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false, MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true,
/*IsThunk=*/false, llvm::AttributeList(), ForDefinition); /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
llvm::SmallVector<StringRef, 32> Features; llvm::SmallVector<StringRef, 32> Features;
Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
@ -2473,15 +2501,34 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
Features.begin(), Features.end(), [&Target](StringRef Feat) { Features.begin(), Features.end(), [&Target](StringRef Feat) {
return !Target.validateCpuSupports(Feat); return !Target.validateCpuSupports(Feat);
}), Features.end()); }), Features.end());
Options.emplace_back(cast<llvm::Function>(Func), Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features);
CodeGenFunction::GetX86CpuSupportsMask(Features));
} }
llvm::sort( llvm::sort(
Options.begin(), Options.end(), Options.begin(), Options.end(),
std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>()); [](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
});
// If the list contains multiple 'default' versions, such as when it contains
// 'pentium' and 'generic', don't emit the call to the generic one (since we
// always run on at least a 'pentium'). We do this by deleting the 'least
// advanced' (read, lowest mangling letter).
while (Options.size() > 1 &&
CodeGenFunction::GetX86CpuSupportsMask(
(Options.end() - 2)->Conditions.Features) == 0) {
StringRef LHSName = (Options.end() - 2)->Function->getName();
StringRef RHSName = (Options.end() - 1)->Function->getName();
if (LHSName.compare(RHSName) < 0)
Options.erase(Options.end() - 2);
else
Options.erase(Options.end() - 1);
}
CodeGenFunction CGF(*this); CodeGenFunction CGF(*this);
CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options); CGF.EmitMultiVersionResolver(ResolverFunc, Options);
} }
/// If an ifunc for the specified mangled name is not in the module, create and /// If an ifunc for the specified mangled name is not in the module, create and

View File

@ -553,6 +553,15 @@ struct CounterCoverageMappingBuilder
completeDeferred(Count, DeferredEndLoc); completeDeferred(Count, DeferredEndLoc);
} }
size_t locationDepth(SourceLocation Loc) {
size_t Depth = 0;
while (Loc.isValid()) {
Loc = getIncludeOrExpansionLoc(Loc);
Depth++;
}
return Depth;
}
/// Pop regions from the stack into the function's list of regions. /// Pop regions from the stack into the function's list of regions.
/// ///
/// Adds all regions from \c ParentIndex to the top of the stack to the /// Adds all regions from \c ParentIndex to the top of the stack to the
@ -567,19 +576,41 @@ struct CounterCoverageMappingBuilder
SourceLocation EndLoc = Region.hasEndLoc() SourceLocation EndLoc = Region.hasEndLoc()
? Region.getEndLoc() ? Region.getEndLoc()
: RegionStack[ParentIndex].getEndLoc(); : RegionStack[ParentIndex].getEndLoc();
size_t StartDepth = locationDepth(StartLoc);
size_t EndDepth = locationDepth(EndLoc);
while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) { while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
// The region ends in a nested file or macro expansion. Create a bool UnnestStart = StartDepth >= EndDepth;
// separate region for each expansion. bool UnnestEnd = EndDepth >= StartDepth;
SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); if (UnnestEnd) {
assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); // The region ends in a nested file or macro expansion. Create a
// separate region for each expansion.
SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
if (EndLoc.isInvalid()) if (EndLoc.isInvalid())
llvm::report_fatal_error("File exit not handled before popRegions"); llvm::report_fatal_error("File exit not handled before popRegions");
EndDepth--;
}
if (UnnestStart) {
// The region begins in a nested file or macro expansion. Create a
// separate region for each expansion.
SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
StartLoc = getIncludeOrExpansionLoc(StartLoc);
if (StartLoc.isInvalid())
llvm::report_fatal_error("File exit not handled before popRegions");
StartDepth--;
}
} }
Region.setStartLoc(StartLoc);
Region.setEndLoc(EndLoc); Region.setEndLoc(EndLoc);
MostRecentLocation = EndLoc; MostRecentLocation = EndLoc;

View File

@ -107,15 +107,19 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (FloatABI == ppc::FloatABI::Soft) if (FloatABI == ppc::FloatABI::Soft)
Features.push_back("-hard-float"); Features.push_back("-hard-float");
ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args); ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args);
if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt) if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
Features.push_back("+secure-plt"); Features.push_back("+secure-plt");
} }
ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) { ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) {
if (Args.getLastArg(options::OPT_msecure_plt)) if (Args.getLastArg(options::OPT_msecure_plt))
return ppc::ReadGOTPtrMode::SecurePlt; return ppc::ReadGOTPtrMode::SecurePlt;
return ppc::ReadGOTPtrMode::Bss; if (Triple.isOSOpenBSD())
return ppc::ReadGOTPtrMode::SecurePlt;
else
return ppc::ReadGOTPtrMode::Bss;
} }
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {

View File

@ -38,7 +38,7 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args); std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
const char *getPPCAsmModeForCPU(StringRef Name); const char *getPPCAsmModeForCPU(StringRef Name);
ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args); const llvm::opt::ArgList &Args);
void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,

View File

@ -138,7 +138,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pie)) if (Args.hasArg(options::OPT_pie))
CmdArgs.push_back("-pie"); CmdArgs.push_back("-pie");
if (Args.hasArg(options::OPT_nopie)) if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-nopie"); CmdArgs.push_back("-nopie");
if (Output.isFilename()) { if (Output.isFilename()) {

View File

@ -16353,67 +16353,82 @@ vec_revb(vector unsigned __int128 __a) {
/* vec_xl */ /* vec_xl */
typedef vector signed char unaligned_vec_schar __attribute__((aligned(1)));
typedef vector unsigned char unaligned_vec_uchar __attribute__((aligned(1)));
typedef vector signed short unaligned_vec_sshort __attribute__((aligned(1)));
typedef vector unsigned short unaligned_vec_ushort __attribute__((aligned(1)));
typedef vector signed int unaligned_vec_sint __attribute__((aligned(1)));
typedef vector unsigned int unaligned_vec_uint __attribute__((aligned(1)));
typedef vector float unaligned_vec_float __attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset,
signed char *__ptr) { signed char *__ptr) {
return *(vector signed char *)(__ptr + __offset); return *(unaligned_vec_schar *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector unsigned char static inline __ATTRS_o_ai vector unsigned char
vec_xl(signed long long __offset, unsigned char *__ptr) { vec_xl(signed long long __offset, unsigned char *__ptr) {
return *(vector unsigned char *)(__ptr + __offset); return *(unaligned_vec_uchar*)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset,
signed short *__ptr) { signed short *__ptr) {
return *(vector signed short *)(__ptr + __offset); return *(unaligned_vec_sshort *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector unsigned short static inline __ATTRS_o_ai vector unsigned short
vec_xl(signed long long __offset, unsigned short *__ptr) { vec_xl(signed long long __offset, unsigned short *__ptr) {
return *(vector unsigned short *)(__ptr + __offset); return *(unaligned_vec_ushort *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset,
signed int *__ptr) { signed int *__ptr) {
return *(vector signed int *)(__ptr + __offset); return *(unaligned_vec_sint *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset,
unsigned int *__ptr) { unsigned int *__ptr) {
return *(vector unsigned int *)(__ptr + __offset); return *(unaligned_vec_uint *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset,
float *__ptr) { float *__ptr) {
return *(vector float *)(__ptr + __offset); return *(unaligned_vec_float *)(__ptr + __offset);
} }
#ifdef __VSX__ #ifdef __VSX__
typedef vector signed long long unaligned_vec_sll __attribute__((aligned(1)));
typedef vector unsigned long long unaligned_vec_ull __attribute__((aligned(1)));
typedef vector double unaligned_vec_double __attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed long long static inline __ATTRS_o_ai vector signed long long
vec_xl(signed long long __offset, signed long long *__ptr) { vec_xl(signed long long __offset, signed long long *__ptr) {
return *(vector signed long long *)(__ptr + __offset); return *(unaligned_vec_sll *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector unsigned long long static inline __ATTRS_o_ai vector unsigned long long
vec_xl(signed long long __offset, unsigned long long *__ptr) { vec_xl(signed long long __offset, unsigned long long *__ptr) {
return *(vector unsigned long long *)(__ptr + __offset); return *(unaligned_vec_ull *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset, static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset,
double *__ptr) { double *__ptr) {
return *(vector double *)(__ptr + __offset); return *(unaligned_vec_double *)(__ptr + __offset);
} }
#endif #endif
#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) #if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
typedef vector signed __int128 unaligned_vec_si128 __attribute__((aligned(1)));
typedef vector unsigned __int128 unaligned_vec_ui128
__attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed __int128 static inline __ATTRS_o_ai vector signed __int128
vec_xl(signed long long __offset, signed __int128 *__ptr) { vec_xl(signed long long __offset, signed __int128 *__ptr) {
return *(vector signed __int128 *)(__ptr + __offset); return *(unaligned_vec_si128 *)(__ptr + __offset);
} }
static inline __ATTRS_o_ai vector unsigned __int128 static inline __ATTRS_o_ai vector unsigned __int128
vec_xl(signed long long __offset, unsigned __int128 *__ptr) { vec_xl(signed long long __offset, unsigned __int128 *__ptr) {
return *(vector unsigned __int128 *)(__ptr + __offset); return *(unaligned_vec_ui128 *)(__ptr + __offset);
} }
#endif #endif
@ -16498,62 +16513,62 @@ vec_xl_be(signed long long __offset, unsigned __int128 *__ptr) {
static inline __ATTRS_o_ai void vec_xst(vector signed char __vec, static inline __ATTRS_o_ai void vec_xst(vector signed char __vec,
signed long long __offset, signed long long __offset,
signed char *__ptr) { signed char *__ptr) {
*(vector signed char *)(__ptr + __offset) = __vec; *(unaligned_vec_schar *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec, static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec,
signed long long __offset, signed long long __offset,
unsigned char *__ptr) { unsigned char *__ptr) {
*(vector unsigned char *)(__ptr + __offset) = __vec; *(unaligned_vec_uchar *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector signed short __vec, static inline __ATTRS_o_ai void vec_xst(vector signed short __vec,
signed long long __offset, signed long long __offset,
signed short *__ptr) { signed short *__ptr) {
*(vector signed short *)(__ptr + __offset) = __vec; *(unaligned_vec_sshort *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec, static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec,
signed long long __offset, signed long long __offset,
unsigned short *__ptr) { unsigned short *__ptr) {
*(vector unsigned short *)(__ptr + __offset) = __vec; *(unaligned_vec_ushort *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector signed int __vec, static inline __ATTRS_o_ai void vec_xst(vector signed int __vec,
signed long long __offset, signed long long __offset,
signed int *__ptr) { signed int *__ptr) {
*(vector signed int *)(__ptr + __offset) = __vec; *(unaligned_vec_sint *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec, static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec,
signed long long __offset, signed long long __offset,
unsigned int *__ptr) { unsigned int *__ptr) {
*(vector unsigned int *)(__ptr + __offset) = __vec; *(unaligned_vec_uint *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector float __vec, static inline __ATTRS_o_ai void vec_xst(vector float __vec,
signed long long __offset, signed long long __offset,
float *__ptr) { float *__ptr) {
*(vector float *)(__ptr + __offset) = __vec; *(unaligned_vec_float *)(__ptr + __offset) = __vec;
} }
#ifdef __VSX__ #ifdef __VSX__
static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec, static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec,
signed long long __offset, signed long long __offset,
signed long long *__ptr) { signed long long *__ptr) {
*(vector signed long long *)(__ptr + __offset) = __vec; *(unaligned_vec_sll *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec, static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec,
signed long long __offset, signed long long __offset,
unsigned long long *__ptr) { unsigned long long *__ptr) {
*(vector unsigned long long *)(__ptr + __offset) = __vec; *(unaligned_vec_ull *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector double __vec, static inline __ATTRS_o_ai void vec_xst(vector double __vec,
signed long long __offset, signed long long __offset,
double *__ptr) { double *__ptr) {
*(vector double *)(__ptr + __offset) = __vec; *(unaligned_vec_double *)(__ptr + __offset) = __vec;
} }
#endif #endif
@ -16561,13 +16576,13 @@ static inline __ATTRS_o_ai void vec_xst(vector double __vec,
static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec, static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec,
signed long long __offset, signed long long __offset,
signed __int128 *__ptr) { signed __int128 *__ptr) {
*(vector signed __int128 *)(__ptr + __offset) = __vec; *(unaligned_vec_si128 *)(__ptr + __offset) = __vec;
} }
static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec, static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec,
signed long long __offset, signed long long __offset,
unsigned __int128 *__ptr) { unsigned __int128 *__ptr) {
*(vector unsigned __int128 *)(__ptr + __offset) = __vec; *(unaligned_vec_ui128 *)(__ptr + __offset) = __vec;
} }
#endif #endif

View File

@ -6092,7 +6092,10 @@ PerformConstructorInitialization(Sema &S,
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo) if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange(); SourceRange ParenOrBraceRange =
(Kind.getKind() == InitializationKind::IK_DirectList)
? SourceRange(LBraceLoc, RBraceLoc)
: Kind.getParenOrBraceRange();
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>( if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
Step.Function.FoundDecl.getDecl())) { Step.Function.FoundDecl.getDecl())) {

View File

@ -5022,13 +5022,16 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef); WriteOpenCLExtensions(SemaRef);
WriteOpenCLExtensionTypes(SemaRef); WriteOpenCLExtensionTypes(SemaRef);
WriteOpenCLExtensionDecls(SemaRef);
WriteCUDAPragmas(SemaRef); WriteCUDAPragmas(SemaRef);
// If we're emitting a module, write out the submodule information. // If we're emitting a module, write out the submodule information.
if (WritingModule) if (WritingModule)
WriteSubmodules(WritingModule); WriteSubmodules(WritingModule);
// We need to have information about submodules to correctly deserialize
// decls from OpenCLExtensionDecls block
WriteOpenCLExtensionDecls(SemaRef);
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
// Write the record containing external, unnamed definitions. // Write the record containing external, unnamed definitions.

View File

@ -475,9 +475,6 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
SingleTy = ResultTy; SingleTy = ResultTy;
if (LSym->getType() != SingleTy) if (LSym->getType() != SingleTy)
return None; return None;
// Substracting unsigned integers is a nightmare.
if (!SingleTy->isSignedIntegerOrEnumerationType())
return None;
} else { } else {
// Don't rearrange other operations. // Don't rearrange other operations.
return None; return None;
@ -485,6 +482,10 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
assert(!SingleTy.isNull() && "We should have figured out the type by now!"); assert(!SingleTy.isNull() && "We should have figured out the type by now!");
// Rearrange signed symbolic expressions only
if (!SingleTy->isSignedIntegerOrEnumerationType())
return None;
SymbolRef RSym = Rhs.getAsSymbol(); SymbolRef RSym = Rhs.getAsSymbol();
if (!RSym || RSym->getType() != SingleTy) if (!RSym || RSym->getType() != SingleTy)
return None; return None;

View File

@ -261,7 +261,11 @@ void DWARFUnit::ExtractDIEsRWLocked() {
} }
if (!m_die_array.empty()) { if (!m_die_array.empty()) {
lldbassert(!m_first_die || m_first_die == m_die_array.front()); if (m_first_die) {
// Only needed for the assertion.
m_first_die.SetEmptyChildren(m_die_array.front().GetEmptyChildren());
lldbassert(m_first_die == m_die_array.front());
}
m_first_die = m_die_array.front(); m_first_die = m_die_array.front();
} }

View File

@ -8,4 +8,4 @@
#define CLANG_VENDOR "FreeBSD " #define CLANG_VENDOR "FreeBSD "
#define SVN_REVISION "346007" #define SVN_REVISION "348686"

View File

@ -7,4 +7,4 @@
#define LLD_REPOSITORY_STRING "FreeBSD" #define LLD_REPOSITORY_STRING "FreeBSD"
// <Upstream revision at import>-<Local identifier in __FreeBSD_version style> // <Upstream revision at import>-<Local identifier in __FreeBSD_version style>
#define LLD_REVISION_STRING "346007-1300001" #define LLD_REVISION_STRING "348686-1300001"

View File

@ -1,2 +1,2 @@
/* $FreeBSD$ */ /* $FreeBSD$ */
#define LLVM_REVISION "svn-r346007" #define LLVM_REVISION "svn-r348686"