diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-06-12 14:03:02 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-06-12 14:03:02 +0000 |
commit | 9374e9ebbc9b95cbd8217d2a14a4584d9a876978 (patch) | |
tree | 9765abc11c0252994c226c538c3a2df010f28f1a | |
parent | 947eb1449054880e65af3acb5a5c77c590aba9ce (diff) |
23 files changed, 280 insertions, 99 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9e4088f94015..163109bf7c9f 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6124,9 +6124,6 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue, MD->getParent()->isUnion())) return false; - if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() && - !HandleUnionActiveMemberChange(Info, Args[0], *This)) - return false; if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), RHSValue)) return false; @@ -7638,6 +7635,15 @@ public: if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; + + // If this is syntactically a simple assignment using a trivial + // assignment operator, start the lifetimes of union members as needed, + // per C++20 [class.union]5. + if (Info.getLangOpts().CPlusPlus20 && OCE && + OCE->getOperator() == OO_Equal && MD->isTrivial() && + !HandleUnionActiveMemberChange(Info, Args[0], ThisVal)) + return false; + Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp index 6266ed72cd5c..93ed0671119f 100644 --- a/clang/lib/Basic/Targets/AVR.cpp +++ b/clang/lib/Basic/Targets/AVR.cpp @@ -24,7 +24,8 @@ namespace targets { struct LLVM_LIBRARY_VISIBILITY MCUInfo { const char *Name; const char *DefineName; - const int NumFlashBanks; // -1 means the device does not support LPM/ELPM. + const int NumFlashBanks; // Set to 0 for the devices do not support LPM/ELPM. + bool IsTiny; // Set to true for the devices belong to the avrtiny family. }; // This list should be kept up-to-date with AVRDevices.td in LLVM. @@ -267,14 +268,14 @@ static MCUInfo AVRMcus[] = { {"atxmega128a1", "__AVR_ATxmega128A1__", 2}, {"atxmega128a1u", "__AVR_ATxmega128A1U__", 2}, {"atxmega128a4u", "__AVR_ATxmega128A4U__", 2}, - {"attiny4", "__AVR_ATtiny4__", 0}, - {"attiny5", "__AVR_ATtiny5__", 0}, - {"attiny9", "__AVR_ATtiny9__", 0}, - {"attiny10", "__AVR_ATtiny10__", 0}, - {"attiny20", "__AVR_ATtiny20__", 0}, - {"attiny40", "__AVR_ATtiny40__", 0}, - {"attiny102", "__AVR_ATtiny102__", 0}, - {"attiny104", "__AVR_ATtiny104__", 0}, + {"attiny4", "__AVR_ATtiny4__", 0, true}, + {"attiny5", "__AVR_ATtiny5__", 0, true}, + {"attiny9", "__AVR_ATtiny9__", 0, true}, + {"attiny10", "__AVR_ATtiny10__", 0, true}, + {"attiny20", "__AVR_ATtiny20__", 0, true}, + {"attiny40", "__AVR_ATtiny40__", 0, true}, + {"attiny102", "__AVR_ATtiny102__", 0, true}, + {"attiny104", "__AVR_ATtiny104__", 0, true}, {"attiny202", "__AVR_ATtiny202__", 1}, {"attiny402", "__AVR_ATtiny402__", 1}, {"attiny204", "__AVR_ATtiny204__", 1}, @@ -325,6 +326,27 @@ void AVRTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { Values.push_back(Info.Name); } +bool AVRTargetInfo::setCPU(const std::string &Name) { + // Set the ABI and CPU fields if parameter Name is a family name. + if (llvm::is_contained(ValidFamilyNames, Name)) { + CPU = Name; + ABI = Name == "avrtiny" ? "avrtiny" : "avr"; + return true; + } + + // Set the ABI field if parameter Name is a device name. + auto It = llvm::find_if( + AVRMcus, [&](const MCUInfo &Info) { return Info.Name == Name; }); + if (It != std::end(AVRMcus)) { + CPU = Name; + ABI = It->IsTiny ? "avrtiny" : "avr"; + return true; + } + + // Parameter Name is neither valid family name nor valid device name. + return false; +} + void AVRTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("AVR"); diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h index a281e2c2cd74..74b012a0923b 100644 --- a/clang/lib/Basic/Targets/AVR.h +++ b/clang/lib/Basic/Targets/AVR.h @@ -74,8 +74,7 @@ public: static const char *const GCCRegNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", - "r20", "r21", "r22", "r23", "r24", "r25", "X", "Y", "Z", "SP" - }; + "r20", "r21", "r22", "r23", "r24", "r25", "X", "Y", "Z", "SP"}; return llvm::makeArrayRef(GCCRegNames); } @@ -169,15 +168,12 @@ public: bool isValidCPUName(StringRef Name) const override; void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; - bool setCPU(const std::string &Name) override { - bool isValid = isValidCPUName(Name); - if (isValid) - CPU = Name; - return isValid; - } + bool setCPU(const std::string &Name) override; + StringRef getABI() const override { return ABI; } protected: std::string CPU; + StringRef ABI; }; } // namespace targets diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 7c9f41e84eaf..06b2da146603 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -9,10 +9,11 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRBuilder.h" #include "Address.h" #include "CodeGenTypeCache.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Type.h" namespace clang { namespace CodeGen { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a37ff8844e88..34f7a421c933 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -38,6 +38,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Type.h" #include "llvm/Transforms/Utils/Local.h" using namespace clang; using namespace CodeGen; @@ -1056,10 +1057,19 @@ void CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, // Call EmitStoreOfScalar except when the lvalue is a bitfield to emit a // primitive store. assert(isa<NoExpansion>(Exp.get())); - if (LV.isBitField()) - EmitStoreThroughLValue(RValue::get(&*AI++), LV); - else - EmitStoreOfScalar(&*AI++, LV); + llvm::Value *Arg = &*AI++; + if (LV.isBitField()) { + EmitStoreThroughLValue(RValue::get(Arg), LV); + } else { + // TODO: currently there are some places are inconsistent in what LLVM + // pointer type they use (see D118744). Once clang uses opaque pointers + // all LLVM pointer types will be the same and we can remove this check. + if (Arg->getType()->isPointerTy()) { + Address Addr = LV.getAddress(*this); + Arg = Builder.CreateBitCast(Arg, Addr.getElementType()); + } + EmitStoreOfScalar(Arg, LV); + } } } diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 4839e22c4b14..7a8a7c916473 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -25,9 +25,20 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" + using namespace clang; using namespace CodeGen; +#ifndef NDEBUG +#include "llvm/Support/CommandLine.h" +// TODO: turn on by default when defined(EXPENSIVE_CHECKS) once check-clang is +// -verify-type-cache clean. +static llvm::cl::opt<bool> VerifyTypeCache( + "verify-type-cache", + llvm::cl::desc("Verify that the type cache matches the computed type"), + llvm::cl::init(false), llvm::cl::Hidden); +#endif + CodeGenTypes::CodeGenTypes(CodeGenModule &cgm) : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()), Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()), @@ -382,9 +393,6 @@ llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(QualType QFT) { RecordsBeingLaidOut.erase(Ty); - if (SkippedLayout) - TypeCache.clear(); - if (RecordsBeingLaidOut.empty()) while (!DeferredRecords.empty()) ConvertRecordDeclType(DeferredRecords.pop_back_val()); @@ -415,11 +423,29 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { if (const RecordType *RT = dyn_cast<RecordType>(Ty)) return ConvertRecordDeclType(RT->getDecl()); - // See if type is already cached. - llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = TypeCache.find(Ty); - // If type is found in map then use it. Otherwise, convert type T. - if (TCI != TypeCache.end()) - return TCI->second; + // The LLVM type we return for a given Clang type may not always be the same, + // most notably when dealing with recursive structs. We mark these potential + // cases with ShouldUseCache below. Builtin types cannot be recursive. + // TODO: when clang uses LLVM opaque pointers we won't be able to represent + // recursive types with LLVM types, making this logic much simpler. + llvm::Type *CachedType = nullptr; + bool ShouldUseCache = + Ty->isBuiltinType() || + (noRecordsBeingLaidOut() && FunctionsBeingProcessed.empty()); + if (ShouldUseCache) { + llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = + TypeCache.find(Ty); + if (TCI != TypeCache.end()) + CachedType = TCI->second; + if (CachedType) { +#ifndef NDEBUG + if (!VerifyTypeCache) + return CachedType; +#else + return CachedType; +#endif + } + } // If we don't have it in the cache, convert it now. llvm::Type *ResultType = nullptr; @@ -797,7 +823,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { assert(ResultType && "Didn't convert a type?"); - TypeCache[Ty] = ResultType; +#ifndef NDEBUG + if (CachedType) { + assert(CachedType == ResultType && + "Cached type doesn't match computed type"); + } +#endif + + if (ShouldUseCache) + TypeCache[Ty] = ResultType; return ResultType; } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 9af3004ebcc5..d83bc9e529a6 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -19,9 +19,9 @@ #include "CodeGenFunction.h" #include "clang/AST/Attr.h" #include "clang/AST/RecordLayout.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Basic/Builtins.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/SwiftCallingConv.h" #include "llvm/ADT/SmallBitVector.h" @@ -33,6 +33,7 @@ #include "llvm/IR/IntrinsicsNVPTX.h" #include "llvm/IR/IntrinsicsS390.h" #include "llvm/IR/Type.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> // std::sort @@ -8272,32 +8273,93 @@ void M68kTargetCodeGenInfo::setTargetAttributes( namespace { class AVRABIInfo : public DefaultABIInfo { +private: + // The total amount of registers can be used to pass parameters. It is 18 on + // AVR, or 6 on AVRTiny. + const unsigned ParamRegs; + // The total amount of registers can be used to pass return value. It is 8 on + // AVR, or 4 on AVRTiny. + const unsigned RetRegs; + public: - AVRABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + AVRABIInfo(CodeGenTypes &CGT, unsigned NPR, unsigned NRR) + : DefaultABIInfo(CGT), ParamRegs(NPR), RetRegs(NRR) {} + + ABIArgInfo classifyReturnType(QualType Ty, bool &LargeRet) const { + if (isAggregateTypeForABI(Ty)) { + // On AVR, a return struct with size less than or equals to 8 bytes is + // returned directly via registers R18-R25. On AVRTiny, a return struct + // with size less than or equals to 4 bytes is returned directly via + // registers R22-R25. + if (getContext().getTypeSize(Ty) <= RetRegs * 8) + return ABIArgInfo::getDirect(); + // A return struct with larger size is returned via a stack + // slot, along with a pointer to it as the function's implicit argument. + LargeRet = true; + return getNaturalAlignIndirect(Ty); + } + // Otherwise we follow the default way which is compatible. + return DefaultABIInfo::classifyReturnType(Ty); + } - ABIArgInfo classifyReturnType(QualType Ty) const { - // A return struct with size less than or equal to 8 bytes is returned - // directly via registers R18-R25. - if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) <= 64) + ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegs) const { + unsigned TySize = getContext().getTypeSize(Ty); + + // An int8 type argument always costs two registers like an int16. + if (TySize == 8 && NumRegs >= 2) { + NumRegs -= 2; + return ABIArgInfo::getExtend(Ty); + } + + // If the argument size is an odd number of bytes, round up the size + // to the next even number. + TySize = llvm::alignTo(TySize, 16); + + // Any type including an array/struct type can be passed in rgisters, + // if there are enough registers left. + if (TySize <= NumRegs * 8) { + NumRegs -= TySize / 8; return ABIArgInfo::getDirect(); - else - return DefaultABIInfo::classifyReturnType(Ty); + } + + // An argument is passed either completely in registers or completely in + // memory. Since there are not enough registers left, current argument + // and all other unprocessed arguments should be passed in memory. + // However we still need to return `ABIArgInfo::getDirect()` other than + // `ABIInfo::getNaturalAlignIndirect(Ty)`, otherwise an extra stack slot + // will be allocated, so the stack frame layout will be incompatible with + // avr-gcc. + NumRegs = 0; + return ABIArgInfo::getDirect(); } - // Just copy the original implementation of DefaultABIInfo::computeInfo(), - // since DefaultABIInfo::classify{Return,Argument}Type() are not virtual. void computeInfo(CGFunctionInfo &FI) const override { + // Decide the return type. + bool LargeRet = false; if (!getCXXABI().classifyReturnType(FI)) - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), LargeRet); + + // Decide each argument type. The total number of registers can be used for + // arguments depends on several factors: + // 1. Arguments of varargs functions are passed on the stack. This applies + // even to the named arguments. So no register can be used. + // 2. Total 18 registers can be used on avr and 6 ones on avrtiny. + // 3. If the return type is a struct with too large size, two registers + // (out of 18/6) will be cost as an implicit pointer argument. + unsigned NumRegs = ParamRegs; + if (FI.isVariadic()) + NumRegs = 0; + else if (LargeRet) + NumRegs -= 2; for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); + I.info = classifyArgumentType(I.type, NumRegs); } }; class AVRTargetCodeGenInfo : public TargetCodeGenInfo { public: - AVRTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(std::make_unique<AVRABIInfo>(CGT)) {} + AVRTargetCodeGenInfo(CodeGenTypes &CGT, unsigned NPR, unsigned NRR) + : TargetCodeGenInfo(std::make_unique<AVRABIInfo>(CGT, NPR, NRR)) {} LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, const VarDecl *D) const override { @@ -11270,8 +11332,14 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::mips64el: return SetCGInfo(new MIPSTargetCodeGenInfo(Types, false)); - case llvm::Triple::avr: - return SetCGInfo(new AVRTargetCodeGenInfo(Types)); + case llvm::Triple::avr: { + // For passing parameters, R8~R25 are used on avr, and R18~R25 are used + // on avrtiny. For passing return value, R18~R25 are used on avr, and + // R22~R25 are used on avrtiny. + unsigned NPR = getTarget().getABI() == "avrtiny" ? 6 : 18; + unsigned NRR = getTarget().getABI() == "avrtiny" ? 4 : 8; + return SetCGInfo(new AVRTargetCodeGenInfo(Types, NPR, NRR)); + } case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp index f68d802c1f95..1ffaa7f6f45b 100644 --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -753,6 +753,7 @@ BreakableLineCommentSection::BreakableLineCommentSection( assert(Tok.is(TT_LineComment) && "line comment section must start with a line comment"); FormatToken *LineTok = nullptr; + const int Minimum = Style.SpacesInLineCommentPrefix.Minimum; // How many spaces we changed in the first line of the section, this will be // applied in all following lines int FirstLineSpaceChange = 0; @@ -775,7 +776,7 @@ BreakableLineCommentSection::BreakableLineCommentSection( Lines[i] = Lines[i].ltrim(Blanks); StringRef IndentPrefix = getLineCommentIndentPrefix(Lines[i], Style); OriginalPrefix[i] = IndentPrefix; - const unsigned SpacesInPrefix = llvm::count(IndentPrefix, ' '); + const int SpacesInPrefix = llvm::count(IndentPrefix, ' '); // On the first line of the comment section we calculate how many spaces // are to be added or removed, all lines after that just get only the @@ -784,12 +785,11 @@ BreakableLineCommentSection::BreakableLineCommentSection( // e.g. from "///" to "//". if (i == 0 || OriginalPrefix[i].rtrim(Blanks) != OriginalPrefix[i - 1].rtrim(Blanks)) { - if (SpacesInPrefix < Style.SpacesInLineCommentPrefix.Minimum && - Lines[i].size() > IndentPrefix.size() && + if (SpacesInPrefix < Minimum && Lines[i].size() > IndentPrefix.size() && isAlphanumeric(Lines[i][IndentPrefix.size()])) { - FirstLineSpaceChange = - Style.SpacesInLineCommentPrefix.Minimum - SpacesInPrefix; - } else if (SpacesInPrefix > Style.SpacesInLineCommentPrefix.Maximum) { + FirstLineSpaceChange = Minimum - SpacesInPrefix; + } else if (static_cast<unsigned>(SpacesInPrefix) > + Style.SpacesInLineCommentPrefix.Maximum) { FirstLineSpaceChange = Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix; } else { @@ -800,10 +800,9 @@ BreakableLineCommentSection::BreakableLineCommentSection( if (Lines[i].size() != IndentPrefix.size()) { PrefixSpaceChange[i] = FirstLineSpaceChange; - if (SpacesInPrefix + PrefixSpaceChange[i] < - Style.SpacesInLineCommentPrefix.Minimum) { - PrefixSpaceChange[i] += Style.SpacesInLineCommentPrefix.Minimum - - (SpacesInPrefix + PrefixSpaceChange[i]); + if (SpacesInPrefix + PrefixSpaceChange[i] < Minimum) { + PrefixSpaceChange[i] += + Minimum - (SpacesInPrefix + PrefixSpaceChange[i]); } assert(Lines[i].size() > IndentPrefix.size()); diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 4c130abd83c3..f5a0b9963b5d 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -414,6 +414,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, --Previous) { Changes[Previous + 1].Spaces -= Shift; Changes[Previous].Spaces += Shift; + Changes[Previous].StartOfTokenColumn += Shift; } } } diff --git a/clang/lib/Headers/__clang_cuda_intrinsics.h b/clang/lib/Headers/__clang_cuda_intrinsics.h index e0875bbcbf4a..3d2f5f40a435 100644 --- a/clang/lib/Headers/__clang_cuda_intrinsics.h +++ b/clang/lib/Headers/__clang_cuda_intrinsics.h @@ -509,7 +509,7 @@ __device__ inline void *__nv_cvta_constant_to_generic_impl(size_t __ptr) { __device__ inline void *__nv_cvta_local_to_generic_impl(size_t __ptr) { return (void *)(void __attribute__((address_space(5))) *)__ptr; } -__device__ inline uint32_t __nvvm_get_smem_pointer(void *__ptr) { +__device__ inline cuuint32_t __nvvm_get_smem_pointer(void *__ptr) { return __nv_cvta_generic_to_shared_impl(__ptr); } } // extern "C" diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a500ad4f0220..32e90ced7b29 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -13314,11 +13314,11 @@ StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses, if (!EndOfTile.isUsable()) return StmtError(); ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), - BO_LE, MakeInnerRef(), EndOfTile.get()); + BO_LT, MakeInnerRef(), EndOfTile.get()); if (!InnerCond1.isUsable()) return StmtError(); ExprResult InnerCond2 = - BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LE, MakeInnerRef(), + BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(), MakeNumIterations()); if (!InnerCond2.isUsable()) return StmtError(); diff --git a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp index 4235c0c13821..945590d0ba8c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -108,7 +108,7 @@ static const NoteTag *getNoteTag(CheckerContext &C, bool CastSucceeds, bool IsKnownCast) { std::string CastToName = CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString() - : CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + : CastToTy.getAsString(); Object = Object->IgnoreParenImpCasts(); return C.getNoteTag( @@ -163,9 +163,9 @@ static const NoteTag *getNoteTag(CheckerContext &C, bool First = true; for (QualType CastToTy: CastToTyVec) { std::string CastToName = - CastToTy->getAsCXXRecordDecl() ? - CastToTy->getAsCXXRecordDecl()->getNameAsString() : - CastToTy->getPointeeCXXRecordDecl()->getNameAsString(); + CastToTy->getAsCXXRecordDecl() + ? CastToTy->getAsCXXRecordDecl()->getNameAsString() + : CastToTy.getAsString(); Out << ' ' << ((CastToTyVec.size() == 1) ? "not" : (First ? "neither" : "nor")) << " a '" << CastToName << '\''; diff --git a/compiler-rt/lib/builtins/atomic.c b/compiler-rt/lib/builtins/atomic.c index 4c3ebb99a513..8dc2f4fc013a 100644 --- a/compiler-rt/lib/builtins/atomic.c +++ b/compiler-rt/lib/builtins/atomic.c @@ -363,6 +363,9 @@ OPTIMISED_CASES #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, xor, ^) OPTIMISED_CASES #undef OPTIMISED_CASE +// Allow build with clang without __c11_atomic_fetch_nand builtin (pre-14) +#if __has_builtin(__c11_atomic_fetch_nand) #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW_NAND(n, lockfree, type) OPTIMISED_CASES #undef OPTIMISED_CASE +#endif diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h index 62064a35aa34..da4ae1688574 100644 --- a/llvm/include/llvm/Support/Base64.h +++ b/llvm/include/llvm/Support/Base64.h @@ -13,6 +13,7 @@ #ifndef LLVM_SUPPORT_BASE64_H #define LLVM_SUPPORT_BASE64_H +#include <cstdint> #include <string> namespace llvm { diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 44f5a750ff5c..937e0572d4a7 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_SIGNALS_H #define LLVM_SUPPORT_SIGNALS_H +#include <cstdint> #include <string> namespace llvm { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp index c1186ae804d2..72e4ffd1311b 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -52,6 +52,8 @@ static MCSubtargetInfo * createAArch64MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { if (CPU.empty()) { CPU = "generic"; + if (FS.empty()) + FS = "+v8a"; if (TT.isArm64e()) CPU = "apple-a12"; diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp index d9d563ead260..02ea0cc23a8c 100644 --- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp +++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp @@ -1290,7 +1290,8 @@ InstructionCost ARMTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, if (!Mask.empty()) { std::pair<InstructionCost, MVT> LT = TLI->getTypeLegalizationCost(DL, Tp); - if (Mask.size() <= LT.second.getVectorNumElements() && + if (LT.second.isVector() && + Mask.size() <= LT.second.getVectorNumElements() && (isVREVMask(Mask, LT.second, 16) || isVREVMask(Mask, LT.second, 32) || isVREVMask(Mask, LT.second, 64))) return ST->getMVEVectorCostFactor(TTI::TCK_RecipThroughput) * LT.first; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 8534a0ad886e..c2f6f5e13160 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -192,6 +192,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Ret: return "MipsISD::Ret"; case MipsISD::ERet: return "MipsISD::ERet"; case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN"; + case MipsISD::FAbs: return "MipsISD::FAbs"; case MipsISD::FMS: return "MipsISD::FMS"; case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; case MipsISD::FPCmp: return "MipsISD::FPCmp"; @@ -353,15 +354,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::SETCC, MVT::f32, Custom); setOperationAction(ISD::SETCC, MVT::f64, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); + setOperationAction(ISD::FABS, MVT::f32, Custom); + setOperationAction(ISD::FABS, MVT::f64, Custom); setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - if (!(TM.Options.NoNaNsFPMath || Subtarget.inAbs2008Mode())) { - setOperationAction(ISD::FABS, MVT::f32, Custom); - setOperationAction(ISD::FABS, MVT::f64, Custom); - } - if (Subtarget.isGP64bit()) { setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::BlockAddress, MVT::i64, Custom); @@ -2421,11 +2419,14 @@ MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert()); } -static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { +SDValue MipsTargetLowering::lowerFABS32(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) const { SDLoc DL(Op); SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); + if (DAG.getTarget().Options.NoNaNsFPMath || Subtarget.inAbs2008Mode()) + return DAG.getNode(MipsISD::FAbs, DL, Op.getValueType(), Op.getOperand(0)); + // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it // to i32. SDValue X = (Op.getValueType() == MVT::f32) @@ -2458,11 +2459,14 @@ static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); } -static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { +SDValue MipsTargetLowering::lowerFABS64(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) const { SDLoc DL(Op); SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); + if (DAG.getTarget().Options.NoNaNsFPMath || Subtarget.inAbs2008Mode()) + return DAG.getNode(MipsISD::FAbs, DL, Op.getValueType(), Op.getOperand(0)); + // Bitcast to integer node. SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0)); diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 3905a18895de..66207193c8b3 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -99,6 +99,9 @@ class TargetRegisterClass; // Floating Point Compare FPCmp, + // Floating point Abs + FAbs, + // Floating point select FSELECT, @@ -540,6 +543,10 @@ class TargetRegisterClass; SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) const; + SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, + bool HasExtractInsert) const; SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 03a545605fe1..ae92604d47ba 100644 --- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -956,6 +956,38 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { break; } + case MipsISD::FAbs: { + MVT ResTy = Node->getSimpleValueType(0); + assert((ResTy == MVT::f64 || ResTy == MVT::f32) && + "Unsupported float type!"); + unsigned Opc = 0; + if (ResTy == MVT::f64) + Opc = (Subtarget->isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32); + else + Opc = Mips::FABS_S; + + if (Subtarget->inMicroMipsMode()) { + switch (Opc) { + case Mips::FABS_D64: + Opc = Mips::FABS_D64_MM; + break; + case Mips::FABS_D32: + Opc = Mips::FABS_D32_MM; + break; + case Mips::FABS_S: + Opc = Mips::FABS_S_MM; + break; + default: + llvm_unreachable("Unknown opcode for MIPS floating point abs!"); + } + } + + ReplaceNode(Node, + CurDAG->getMachineNode(Opc, DL, ResTy, Node->getOperand(0))); + + return true; + } + // Manually match MipsISD::Ins nodes to get the correct instruction. It has // to be done in this fashion so that we respect the differences between // dins and dinsm, as the difference is that the size operand has the range diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index cc5738a5d7b6..48be7e0860df 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -491,15 +491,13 @@ bool PPCTTIImpl::mightUseCTR(BasicBlock *BB, TargetLibraryInfo *LibInfo, case Intrinsic::experimental_constrained_sin: case Intrinsic::experimental_constrained_cos: return true; - // There is no corresponding FMA instruction for PPC double double. - // Thus, we need to disable CTR loop generation for this type. - case Intrinsic::fmuladd: case Intrinsic::copysign: if (CI->getArgOperand(0)->getType()->getScalarType()-> isPPC_FP128Ty()) return true; else continue; // ISD::FCOPYSIGN is never a library call. + case Intrinsic::fmuladd: case Intrinsic::fma: Opcode = ISD::FMA; break; case Intrinsic::sqrt: Opcode = ISD::FSQRT; break; case Intrinsic::floor: Opcode = ISD::FFLOOR; break; diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 318c4c06f0f7..2635d0a213ff 100644 --- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -1173,6 +1173,8 @@ bool LoopIdiomRecognize::processLoopStridedStore( CallInst *NewCall; if (SplatValue) { AAMDNodes AATags = TheStore->getAAMetadata(); + for (Instruction *Store : Stores) + AATags = AATags.merge(Store->getAAMetadata()); if (auto CI = dyn_cast<ConstantInt>(NumBytes)) AATags = AATags.extendTo(CI->getZExtValue()); else @@ -1420,26 +1422,19 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad( // If the store is a memcpy instruction, we must check if it will write to // the load memory locations. So remove it from the ignored stores. - if (IsMemCpy) - IgnoredInsts.erase(TheStore); MemmoveVerifier Verifier(*LoadBasePtr, *StoreBasePtr, *DL); + if (IsMemCpy && !Verifier.IsSameObject) + IgnoredInsts.erase(TheStore); if (mayLoopAccessLocation(LoadBasePtr, ModRefInfo::Mod, CurLoop, BECount, StoreSizeSCEV, *AA, IgnoredInsts)) { - if (!IsMemCpy) { - ORE.emit([&]() { - return OptimizationRemarkMissed(DEBUG_TYPE, "LoopMayAccessLoad", - TheLoad) - << ore::NV("Inst", InstRemark) << " in " - << ore::NV("Function", TheStore->getFunction()) - << " function will not be hoisted: " - << ore::NV("Reason", "The loop may access load location"); - }); - return Changed; - } - // At this point loop may access load only for memcpy in same underlying - // object. If that's not the case bail out. - if (!Verifier.IsSameObject) - return Changed; + ORE.emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "LoopMayAccessLoad", TheLoad) + << ore::NV("Inst", InstRemark) << " in " + << ore::NV("Function", TheStore->getFunction()) + << " function will not be hoisted: " + << ore::NV("Reason", "The loop may access load location"); + }); + return Changed; } bool UseMemMove = IsMemCpy ? Verifier.IsSameObject : LoopAccessStore; diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 9a10535c9310..1c350a2585d0 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -2350,7 +2350,7 @@ static bool markAliveBlocks(Function &F, changeToUnreachable(II, false, DTU); Changed = true; } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) { - if (II->use_empty() && II->onlyReadsMemory()) { + if (II->use_empty() && !II->mayHaveSideEffects()) { // jump to the normal destination branch. BasicBlock *NormalDestBB = II->getNormalDest(); BasicBlock *UnwindDestBB = II->getUnwindDest(); |