From 30b7da72f2abef7cad4d1b38e141e7d2ef170d88 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Wed, 8 Jan 2025 05:19:21 -0500 Subject: [PATCH 001/163] [lldb][OpenBSD][NFC] Replace tab with spaces (#122041) --- lldb/source/Host/openbsd/Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp index a4dc3918acfd0..76d8c4faa3863 100644 --- a/lldb/source/Host/openbsd/Host.cpp +++ b/lldb/source/Host/openbsd/Host.cpp @@ -127,7 +127,7 @@ static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { process_info.SetUserID(proc_kinfo.p_ruid); process_info.SetGroupID(proc_kinfo.p_rgid); process_info.SetEffectiveUserID(proc_kinfo.p_uid); - process_info.SetEffectiveGroupID(proc_kinfo.p_gid); + process_info.SetEffectiveGroupID(proc_kinfo.p_gid); return true; } } From 20d7fa1cc33c72f68bd41fa616b2dab4a4967618 Mon Sep 17 00:00:00 2001 From: gbMattN <146744444+gbMattN@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:20:20 +0000 Subject: [PATCH 002/163] [TySan] Added a 'print_stacktrace' flag for more detailed errors (#121756) Raised in issue #121697 --- compiler-rt/lib/tysan/tysan.cpp | 6 +++++- compiler-rt/lib/tysan/tysan_flags.inc | 3 +++ compiler-rt/test/tysan/print_stacktrace.c | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 compiler-rt/test/tysan/print_stacktrace.c diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp index 39d78e7c95e0c..9c87b4782671a 100644 --- a/compiler-rt/lib/tysan/tysan.cpp +++ b/compiler-rt/lib/tysan/tysan.cpp @@ -197,10 +197,14 @@ static void reportError(void *Addr, int Size, tysan_type_descriptor *TD, Printf("\n"); if (pc) { + uptr top = 0; + uptr bottom = 0; + if (flags().print_stacktrace) + GetThreadStackTopAndBottom(false, &top, &bottom); bool request_fast = StackTrace::WillUseFastUnwind(true); BufferedStackTrace ST; - ST.Unwind(kStackTraceMax, pc, bp, 0, 0, 0, request_fast); + ST.Unwind(kStackTraceMax, pc, bp, 0, top, bottom, request_fast); ST.Print(); } else { Printf("\n"); diff --git a/compiler-rt/lib/tysan/tysan_flags.inc b/compiler-rt/lib/tysan/tysan_flags.inc index 98b6591f844ef..be65c8e828794 100644 --- a/compiler-rt/lib/tysan/tysan_flags.inc +++ b/compiler-rt/lib/tysan/tysan_flags.inc @@ -15,3 +15,6 @@ // TYSAN_FLAG(Type, Name, DefaultValue, Description) // See COMMON_FLAG in sanitizer_flags.inc for more details. + +TYSAN_FLAG(bool, print_stacktrace, false, + "Include full stacktrace into an error report") diff --git a/compiler-rt/test/tysan/print_stacktrace.c b/compiler-rt/test/tysan/print_stacktrace.c new file mode 100644 index 0000000000000..3ffb6063377d9 --- /dev/null +++ b/compiler-rt/test/tysan/print_stacktrace.c @@ -0,0 +1,22 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck --check-prefixes=CHECK,CHECK-SHORT %s < %t.out + +// RUN: %env_tysan_opts=print_stacktrace=1 %run %t >%t.out 2>&1 +// RUN: FileCheck --check-prefixes=CHECK,CHECK-LONG %s < %t.out + +float *P; +void zero_array() { + int i; + for (i = 0; i < 1; ++i) + P[i] = 0.0f; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type p1 float + // CHECK: {{#0 0x.* in zero_array .*print_stacktrace.c:}}[[@LINE-3]] + // CHECK-SHORT-NOT: {{#1 0x.* in main .*print_stacktrace.c}} + // CHECK-LONG-NEXT: {{#1 0x.* in main .*print_stacktrace.c}} +} + +int main() { + P = (float *)&P; + zero_array(); +} From bfa711a970d50c9101c8962609f9aad4f5395825 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 8 Jan 2025 11:26:57 +0100 Subject: [PATCH 003/163] [InstCombine] Use combineMetadataForCSE in phi of loads fold Use combineMetadataForCSE instead of manually enumerating known metadata kinds. This is a typical sinking transform for which combineMetadataForCSE is safe to use (with DoesKMove=true). Part of https://github.com/llvm/llvm-project/issues/121495. --- .../Transforms/InstCombine/InstCombinePHI.cpp | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index 272a1942c3350..80308bf92dbbc 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -765,33 +765,14 @@ Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) { NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); LoadInst *NewLI = new LoadInst(FirstLI->getType(), NewPN, "", IsVolatile, LoadAlignment); - - unsigned KnownIDs[] = { - LLVMContext::MD_tbaa, - LLVMContext::MD_range, - LLVMContext::MD_invariant_load, - LLVMContext::MD_alias_scope, - LLVMContext::MD_noalias, - LLVMContext::MD_nonnull, - LLVMContext::MD_align, - LLVMContext::MD_dereferenceable, - LLVMContext::MD_dereferenceable_or_null, - LLVMContext::MD_access_group, - LLVMContext::MD_noundef, - }; - - for (unsigned ID : KnownIDs) - NewLI->setMetadata(ID, FirstLI->getMetadata(ID)); + NewLI->copyMetadata(*FirstLI); // Add all operands to the new PHI and combine TBAA metadata. for (auto Incoming : drop_begin(zip(PN.blocks(), PN.incoming_values()))) { BasicBlock *BB = std::get<0>(Incoming); Value *V = std::get<1>(Incoming); LoadInst *LI = cast(V); - // FIXME: https://github.com/llvm/llvm-project/issues/121495 - // Call combineMetadataForCSE instead, so that an explicit set of KnownIDs - // doesn't need to be maintained here. - combineMetadata(NewLI, LI, KnownIDs, true); + combineMetadataForCSE(NewLI, LI, true); Value *NewInVal = LI->getOperand(0); if (NewInVal != InVal) InVal = nullptr; From edf14ed6b182b9ae9efa0c854f3d4744bb67bf08 Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Wed, 8 Jan 2025 19:40:16 +0800 Subject: [PATCH 004/163] [Clang] Don't form a type constraint if the concept is invalid (#122065) After 0dedd6fe1 and 03229e7c0, invalid concept declarations might lack expressions for evaluation and normalization. This could make it crash in certain scenarios, apart from the one of evaluation concepts showed in 03229e7c0, there's also an issue when checking specializations where the normalization also relies on a non-null expression. This patch prevents that by avoiding building up a type constraint in such situations, thereafter the template parameter wouldn't have a concept specialization of a null expression. With this patch, the assumption in ASTWriterDecl is no longer valid. Namely, HasConstraint and TypeConstraintInitialized must now represent different meanings for both source fidelity and semantic requirements. Fixes https://github.com/llvm/llvm-project/issues/115004 Fixes https://github.com/llvm/llvm-project/issues/121980 --- clang/lib/Sema/SemaTemplate.cpp | 3 +++ clang/lib/Serialization/ASTReaderDecl.cpp | 3 ++- clang/lib/Serialization/ASTWriterDecl.cpp | 5 +++-- clang/test/SemaTemplate/concepts.cpp | 12 ++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 20ec2fbeaa6a8..ce672b00893b0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4557,6 +4557,9 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, const TemplateArgumentListInfo *TemplateArgs) { assert(NamedConcept && "A concept template id without a template?"); + if (NamedConcept->isInvalidDecl()) + return ExprError(); + llvm::SmallVector SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList( NamedConcept, ConceptNameInfo.getLoc(), diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 719bc0d06f5b1..8c60e85c93d70 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2663,7 +2663,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { D->setDeclaredWithTypename(Record.readInt()); - if (D->hasTypeConstraint()) { + bool TypeConstraintInitialized = D->hasTypeConstraint() && Record.readBool(); + if (TypeConstraintInitialized) { ConceptReference *CR = nullptr; if (Record.readBool()) CR = Record.readConceptReference(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 75c1d9a6d438c..f8ed155ca389d 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1951,7 +1951,8 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { Record.push_back(D->wasDeclaredWithTypename()); const TypeConstraint *TC = D->getTypeConstraint(); - assert((bool)TC == D->hasTypeConstraint()); + if (D->hasTypeConstraint()) + Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr); if (TC) { auto *CR = TC->getConceptReference(); Record.push_back(CR != nullptr); @@ -1969,7 +1970,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { if (OwnsDefaultArg) Record.AddTemplateArgumentLoc(D->getDefaultArgument()); - if (!TC && !OwnsDefaultArg && + if (!D->hasTypeConstraint() && !OwnsDefaultArg && D->getDeclContext() == D->getLexicalDeclContext() && !D->isInvalidDecl() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && !D->isImplicit() && diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 312469313fc53..f335ca3bd22bc 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1165,3 +1165,15 @@ concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'} bool val2 = C; } // namespace GH109780 + +namespace GH121980 { + +template +concept has_member_difference_type; // expected-error {{expected '='}} + +template struct incrementable_traits; // expected-note {{declared here}} + +template +struct incrementable_traits; // expected-error {{not more specialized than the primary}} + +} From 9fc152d25ea1610efe2824c763e96e790d520910 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 8 Jan 2025 11:54:01 +0000 Subject: [PATCH 005/163] [TBAA] Add Clang pointer TBAA test with void *. --- clang/test/CodeGen/tbaa-pointers.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c index 6aee2ff3717ac..0125d622faffa 100644 --- a/clang/test/CodeGen/tbaa-pointers.c +++ b/clang/test/CodeGen/tbaa-pointers.c @@ -205,6 +205,24 @@ void unamed_struct_typedef(TypedefS *ptr) { ptr->i1 = 0; } +int void_ptrs(void **ptr) { +// COMMON-LABEL: define i32 @void_ptrs( +// COMMON-SAME: ptr noundef [[PTRA:%.+]]) +// COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 +// DISABLE-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DISABLE-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DISABLE-NEXT: [[L1:%.+]] = load ptr, ptr [[L0]], align 8, !tbaa [[ANYPTR]] +// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2VOID:!.+]] +// DEFAULT-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2VOID]] +// DEFAULT-NEXT: [[L1:%.+]] = load ptr, ptr [[L0]], align 8, !tbaa [[P1VOID:!.+]] +// COMMON-NEXT: [[BOOL:%.+]] = icmp ne ptr [[L1]], null +// COMMON-NEXT: [[BOOL_EXT:%.+]] = zext i1 [[BOOL]] to i64 +// COMMON-NEXT: [[COND:%.+]] = select i1 [[BOOL]], i32 0, i32 1 +// COMMON-NEXT: ret i32 [[COND]] + + return *ptr ? 0 : 1; +} + // DEFAULT: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0} // DEFAULT: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0} // DISABLE: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0} @@ -237,3 +255,7 @@ void unamed_struct_typedef(TypedefS *ptr) { // COMMON: [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0} // COMMON: [[INT_TY]] = !{!"int", [[CHAR]], i64 0} // DEFAULT: [[P1TYPEDEF]] = !{[[ANY_POINTER]], [[ANY_POINTER]], i64 0} +// DEFAULT: [[P2VOID]] = !{[[P2VOID_TY:!.+]], [[P2VOID_TY]], i64 0} +// DEFAULT: [[P2VOID_TY]] = !{!"p2 void", [[ANY_POINTER]], i64 0} +// DEFAULT: [[P1VOID]] = !{[[P1VOID_TY:!.+]], [[P1VOID_TY]], i64 0} +// DEFAULT: [[P1VOID_TY]] = !{!"p1 void", [[ANY_POINTER]], i64 0} From 03e7862962d01a5605f1eeeb26626083584945ff Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 8 Jan 2025 20:02:49 +0800 Subject: [PATCH 006/163] [ValueTracking] Move `getFlippedStrictnessPredicateAndConstant` into ValueTracking. NFC. (#122064) Needed by https://github.com/llvm/llvm-project/pull/121958. --- llvm/include/llvm/Analysis/ValueTracking.h | 7 ++ .../Transforms/InstCombine/InstCombiner.h | 6 -- llvm/lib/Analysis/ValueTracking.cpp | 74 ++++++++++++++++ .../InstCombine/InstCombineCompares.cpp | 84 +------------------ .../InstCombine/InstCombineSelect.cpp | 6 +- 5 files changed, 87 insertions(+), 90 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 8aa024a72afc8..b4918c2d1e8a1 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -1102,6 +1102,13 @@ bool mustExecuteUBIfPoisonOnPathTo(Instruction *Root, Instruction *OnPathTo, DominatorTree *DT); +/// Convert an integer comparison with a constant RHS into an equivalent +/// form with the strictness flipped predicate. Return the new predicate and +/// corresponding constant RHS if possible. Otherwise return std::nullopt. +/// E.g., (icmp sgt X, 0) -> (icmp sle X, 1). +std::optional> +getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C); + /// Specific patterns of select instructions we can match. enum SelectPatternFlavor { SPF_UNKNOWN = 0, diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h index 71592058e3456..fa6b60cba15aa 100644 --- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h +++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h @@ -184,12 +184,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner { return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1)); } - std::optional> static getFlippedStrictnessPredicateAndConstant(CmpPredicate - Pred, - Constant *C); - static bool shouldAvoidAbsorbingNotIntoSelect(const SelectInst &SI) { // a ? b : false and a ? true : b are the canonical form of logical and/or. // This includes !a ? b : false and !a ? true : b. Absorbing the not into diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 2f6e869ae7b73..0eb43dd581acc 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -8641,6 +8641,80 @@ SelectPatternResult llvm::getSelectPattern(CmpInst::Predicate Pred, } } +std::optional> +llvm::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C) { + assert(ICmpInst::isRelational(Pred) && ICmpInst::isIntPredicate(Pred) && + "Only for relational integer predicates."); + if (isa(C)) + return std::nullopt; + + Type *Type = C->getType(); + bool IsSigned = ICmpInst::isSigned(Pred); + + CmpInst::Predicate UnsignedPred = ICmpInst::getUnsignedPredicate(Pred); + bool WillIncrement = + UnsignedPred == ICmpInst::ICMP_ULE || UnsignedPred == ICmpInst::ICMP_UGT; + + // Check if the constant operand can be safely incremented/decremented + // without overflowing/underflowing. + auto ConstantIsOk = [WillIncrement, IsSigned](ConstantInt *C) { + return WillIncrement ? !C->isMaxValue(IsSigned) : !C->isMinValue(IsSigned); + }; + + Constant *SafeReplacementConstant = nullptr; + if (auto *CI = dyn_cast(C)) { + // Bail out if the constant can't be safely incremented/decremented. + if (!ConstantIsOk(CI)) + return std::nullopt; + } else if (auto *FVTy = dyn_cast(Type)) { + unsigned NumElts = FVTy->getNumElements(); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = C->getAggregateElement(i); + if (!Elt) + return std::nullopt; + + if (isa(Elt)) + continue; + + // Bail out if we can't determine if this constant is min/max or if we + // know that this constant is min/max. + auto *CI = dyn_cast(Elt); + if (!CI || !ConstantIsOk(CI)) + return std::nullopt; + + if (!SafeReplacementConstant) + SafeReplacementConstant = CI; + } + } else if (isa(C->getType())) { + // Handle scalable splat + Value *SplatC = C->getSplatValue(); + auto *CI = dyn_cast_or_null(SplatC); + // Bail out if the constant can't be safely incremented/decremented. + if (!CI || !ConstantIsOk(CI)) + return std::nullopt; + } else { + // ConstantExpr? + return std::nullopt; + } + + // It may not be safe to change a compare predicate in the presence of + // undefined elements, so replace those elements with the first safe constant + // that we found. + // TODO: in case of poison, it is safe; let's replace undefs only. + if (C->containsUndefOrPoisonElement()) { + assert(SafeReplacementConstant && "Replacement constant not set"); + C = Constant::replaceUndefsWith(C, SafeReplacementConstant); + } + + CmpInst::Predicate NewPred = CmpInst::getFlippedStrictnessPredicate(Pred); + + // Increment or decrement the constant. + Constant *OneOrNegOne = ConstantInt::get(Type, WillIncrement ? 1 : -1, true); + Constant *NewC = ConstantExpr::getAdd(C, OneOrNegOne); + + return std::make_pair(NewPred, NewC); +} + static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred, FastMathFlags FMF, Value *CmpLHS, Value *CmpRHS, diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d764f845ffd43..2e45725759949 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2485,9 +2485,8 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp, // icmp ule i64 (shl X, 32), 8589934592 -> // icmp ule i32 (trunc X, i32), 2 -> // icmp ult i32 (trunc X, i32), 3 - if (auto FlippedStrictness = - InstCombiner::getFlippedStrictnessPredicateAndConstant( - Pred, ConstantInt::get(ShType->getContext(), C))) { + if (auto FlippedStrictness = getFlippedStrictnessPredicateAndConstant( + Pred, ConstantInt::get(ShType->getContext(), C))) { CmpPred = FlippedStrictness->first; RHSC = cast(FlippedStrictness->second)->getValue(); } @@ -3280,8 +3279,7 @@ bool InstCombinerImpl::matchThreeWayIntCompare(SelectInst *SI, Value *&LHS, if (PredB == ICmpInst::ICMP_SGT && isa(RHS2)) { // x sgt C-1 <--> x sge C <--> not(x slt C) auto FlippedStrictness = - InstCombiner::getFlippedStrictnessPredicateAndConstant( - PredB, cast(RHS2)); + getFlippedStrictnessPredicateAndConstant(PredB, cast(RHS2)); if (!FlippedStrictness) return false; assert(FlippedStrictness->first == ICmpInst::ICMP_SGE && @@ -6908,79 +6906,6 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { return nullptr; } -std::optional> -InstCombiner::getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, - Constant *C) { - assert(ICmpInst::isRelational(Pred) && ICmpInst::isIntPredicate(Pred) && - "Only for relational integer predicates."); - - Type *Type = C->getType(); - bool IsSigned = ICmpInst::isSigned(Pred); - - CmpInst::Predicate UnsignedPred = ICmpInst::getUnsignedPredicate(Pred); - bool WillIncrement = - UnsignedPred == ICmpInst::ICMP_ULE || UnsignedPred == ICmpInst::ICMP_UGT; - - // Check if the constant operand can be safely incremented/decremented - // without overflowing/underflowing. - auto ConstantIsOk = [WillIncrement, IsSigned](ConstantInt *C) { - return WillIncrement ? !C->isMaxValue(IsSigned) : !C->isMinValue(IsSigned); - }; - - Constant *SafeReplacementConstant = nullptr; - if (auto *CI = dyn_cast(C)) { - // Bail out if the constant can't be safely incremented/decremented. - if (!ConstantIsOk(CI)) - return std::nullopt; - } else if (auto *FVTy = dyn_cast(Type)) { - unsigned NumElts = FVTy->getNumElements(); - for (unsigned i = 0; i != NumElts; ++i) { - Constant *Elt = C->getAggregateElement(i); - if (!Elt) - return std::nullopt; - - if (isa(Elt)) - continue; - - // Bail out if we can't determine if this constant is min/max or if we - // know that this constant is min/max. - auto *CI = dyn_cast(Elt); - if (!CI || !ConstantIsOk(CI)) - return std::nullopt; - - if (!SafeReplacementConstant) - SafeReplacementConstant = CI; - } - } else if (isa(C->getType())) { - // Handle scalable splat - Value *SplatC = C->getSplatValue(); - auto *CI = dyn_cast_or_null(SplatC); - // Bail out if the constant can't be safely incremented/decremented. - if (!CI || !ConstantIsOk(CI)) - return std::nullopt; - } else { - // ConstantExpr? - return std::nullopt; - } - - // It may not be safe to change a compare predicate in the presence of - // undefined elements, so replace those elements with the first safe constant - // that we found. - // TODO: in case of poison, it is safe; let's replace undefs only. - if (C->containsUndefOrPoisonElement()) { - assert(SafeReplacementConstant && "Replacement constant not set"); - C = Constant::replaceUndefsWith(C, SafeReplacementConstant); - } - - CmpInst::Predicate NewPred = CmpInst::getFlippedStrictnessPredicate(Pred); - - // Increment or decrement the constant. - Constant *OneOrNegOne = ConstantInt::get(Type, WillIncrement ? 1 : -1, true); - Constant *NewC = ConstantExpr::getAdd(C, OneOrNegOne); - - return std::make_pair(NewPred, NewC); -} - /// If we have an icmp le or icmp ge instruction with a constant operand, turn /// it into the appropriate icmp lt or icmp gt instruction. This transform /// allows them to be folded in visitICmpInst. @@ -6996,8 +6921,7 @@ static ICmpInst *canonicalizeCmpWithConstant(ICmpInst &I) { if (!Op1C) return nullptr; - auto FlippedStrictness = - InstCombiner::getFlippedStrictnessPredicateAndConstant(Pred, Op1C); + auto FlippedStrictness = getFlippedStrictnessPredicateAndConstant(Pred, Op1C); if (!FlippedStrictness) return nullptr; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index c58a63483a717..1eca17751bacb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1689,8 +1689,7 @@ tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp, return nullptr; // Check the constant we'd have with flipped-strictness predicate. - auto FlippedStrictness = - InstCombiner::getFlippedStrictnessPredicateAndConstant(Pred, C0); + auto FlippedStrictness = getFlippedStrictnessPredicateAndConstant(Pred, C0); if (!FlippedStrictness) return nullptr; @@ -1970,8 +1969,7 @@ static Value *foldSelectWithConstOpToBinOp(ICmpInst *Cmp, Value *TrueVal, Value *RHS; SelectPatternFlavor SPF; const DataLayout &DL = BOp->getDataLayout(); - auto Flipped = - InstCombiner::getFlippedStrictnessPredicateAndConstant(Predicate, C1); + auto Flipped = getFlippedStrictnessPredicateAndConstant(Predicate, C1); if (C3 == ConstantFoldBinaryOpOperands(Opcode, C1, C2, DL)) { SPF = getSelectPattern(Predicate).Flavor; From 7060d2a12b6da41ab0e3d86ff7fe1501e4f40769 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 8 Jan 2025 20:33:50 +0800 Subject: [PATCH 007/163] [CodeGenPrepare] Regenerate test `X86/codegen-prepare-addrmode-sext.ll` (#122101) Needed by https://github.com/llvm/llvm-project/pull/71058 --- .../X86/codegen-prepare-addrmode-sext.ll | 457 +++++++++++------- 1 file changed, 285 insertions(+), 172 deletions(-) diff --git a/llvm/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll b/llvm/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll index c611e89f27865..f3070cd55903b 100644 --- a/llvm/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll +++ b/llvm/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -S -passes='require,function(codegenprepare)' %s -o - | FileCheck %s ; This file tests the different cases what are involved when codegen prepare ; tries to get sign/zero extension out of the way of addressing mode. @@ -9,14 +10,17 @@ target triple = "x86_64-apple-macosx" ; Check that we correctly promote both operands of the promotable add. -; CHECK-LABEL: @twoArgsPromotion -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64 -; CHECK: [[ARG2SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg2 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], [[ARG2SEXT]] -; CHECK: inttoptr i64 [[PROMOTED]] to ptr -; CHECK: ret define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) { - %add = add nsw i32 %arg1, %arg2 +; CHECK-LABEL: define i8 @twoArgsPromotion( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i32 [[ARG1]] to i64 +; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i32 [[ARG2]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], [[PROMOTED2]] +; CHECK-NEXT: [[BASE:%.*]] = inttoptr i64 [[ADD]] to ptr +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[BASE]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nsw i32 %arg1, %arg2 %sextadd = sext i32 %add to i64 %base = inttoptr i64 %sextadd to ptr %res = load i8, ptr %base @@ -28,11 +32,16 @@ define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) { ; Otherwise, we will increase the number of instruction executed. ; (This is a heuristic of course, because the new sext could have been ; merged with something else.) -; CHECK-LABEL: @twoArgsNoPromotion -; CHECK: add nsw i32 %arg1, %arg2 -; CHECK: ret define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, ptr %base) { - %add = add nsw i32 %arg1, %arg2 +; CHECK-LABEL: define i8 @twoArgsNoPromotion( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: [[SEXTADD:%.*]] = sext i32 [[ADD]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[SEXTADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nsw i32 %arg1, %arg2 %sextadd = sext i32 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -41,11 +50,16 @@ define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, ptr %base) { ; Check that we do not promote when the related instruction does not have ; the nsw flag. -; CHECK-LABEL: @noPromotion -; CHECK-NOT: add i64 -; CHECK: ret define i8 @noPromotion(i32 %arg1, i32 %arg2, ptr %base) { - %add = add i32 %arg1, %arg2 +; CHECK-LABEL: define i8 @noPromotion( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: [[SEXTADD:%.*]] = sext i32 [[ADD]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[SEXTADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add i32 %arg1, %arg2 %sextadd = sext i32 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -53,13 +67,16 @@ define i8 @noPromotion(i32 %arg1, i32 %arg2, ptr %base) { } ; Check that we correctly promote constant arguments. -; CHECK-LABEL: @oneArgPromotion -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotion(i32 %arg1, ptr %base) { - %add = add nsw i32 %arg1, 1 +; CHECK-LABEL: define i8 @oneArgPromotion( +; CHECK-SAME: i32 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i32 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nsw i32 %arg1, 1 %sextadd = sext i32 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -67,14 +84,17 @@ define i8 @oneArgPromotion(i32 %arg1, ptr %base) { } ; Check that we are able to merge a sign extension with a zero extension. -; CHECK-LABEL: @oneArgPromotionZExt -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionZExt(i8 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionZExt( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED2:%.*]] = zext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %zext = zext i8 %arg1 to i32 - %add = add nsw i32 %zext, 1 + %add = add nsw i32 %zext, 1 %sextadd = sext i32 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -88,11 +108,14 @@ define i8 @oneArgPromotionZExt(i8 %arg1, ptr %base) { ; more thing in the addressing mode. Therefore the modification is ; rolled back. ; Still, this test case exercises the desired code path. -; CHECK-LABEL: @oneArgPromotionCstZExt -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 0, 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionCstZExt(ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionCstZExt( +; CHECK-SAME: ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 0, 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %cst = zext i16 undef to i32 %add = add nsw i32 %cst, 1 %sextadd = sext i32 %add to i64 @@ -103,15 +126,18 @@ define i8 @oneArgPromotionCstZExt(ptr %base) { ; Check that we do not promote truncate when we cannot determine the ; bits that are dropped. -; CHECK-LABEL: @oneArgPromotionBlockTrunc1 -; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 %arg1 to i8 -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionBlockTrunc1( +; CHECK-SAME: i32 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ARG1]] to i8 +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i8 [[TRUNC]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %trunc = trunc i32 %arg1 to i8 - %add = add nsw i8 %trunc, 1 + %add = add nsw i8 %trunc, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -120,17 +146,20 @@ define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, ptr %base) { ; Check that we do not promote truncate when we cannot determine all the ; bits that are dropped. -; CHECK-LABEL: @oneArgPromotionBlockTrunc2 -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i16 %arg1 to i32 -; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8 -; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionBlockTrunc2( +; CHECK-SAME: i16 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[SEXTARG1:%.*]] = sext i16 [[ARG1]] to i32 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SEXTARG1]] to i8 +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i8 [[TRUNC]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = sext i16 %arg1 to i32 %trunc = trunc i32 %sextarg1 to i8 - %add = add nsw i8 %trunc, 1 + %add = add nsw i8 %trunc, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -139,15 +168,18 @@ define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, ptr %base) { ; Check that we are able to promote truncate when we know all the bits ; that are dropped. -; CHECK-LABEL: @oneArgPromotionPassTruncKeepSExt -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionPassTruncKeepSExt( +; CHECK-SAME: i1 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i1 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = sext i1 %arg1 to i32 %trunc = trunc i32 %sextarg1 to i8 - %add = add nsw i8 %trunc, 1 + %add = add nsw i8 %trunc, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -156,17 +188,19 @@ define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, ptr %base) { ; On X86 truncate are free. Check that we are able to promote the add ; to be used as addressing mode and that we insert a truncate for the other -; use. -; CHECK-LABEL: @oneArgPromotionTruncInsert -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8 -; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, ptr [[GEP]] -; CHECK: add i8 [[LOAD]], [[TRUNC]] -; CHECK: ret +; use. define i8 @oneArgPromotionTruncInsert(i8 %arg1, ptr %base) { - %add = add nsw i8 %arg1, 1 +; CHECK-LABEL: define i8 @oneArgPromotionTruncInsert( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[PROMOTED:%.*]] = trunc i64 [[ADD]] to i8 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[FINALRES:%.*]] = add i8 [[RES]], [[PROMOTED]] +; CHECK-NEXT: ret i8 [[FINALRES]] +; + %add = add nsw i8 %arg1, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -175,15 +209,20 @@ define i8 @oneArgPromotionTruncInsert(i8 %arg1, ptr %base) { } ; Cannot sext from a larger type than the promoted type. -; CHECK-LABEL: @oneArgPromotionLargerType -; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i128 %arg1 to i8 -; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionLargerType(i128 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionLargerType( +; CHECK-SAME: i128 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i128 [[ARG1]] to i8 +; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i8 [[TRUNC]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[PROMOTED:%.*]] = trunc i64 [[ADD]] to i8 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[FINALRES:%.*]] = add i8 [[RES]], [[PROMOTED]] +; CHECK-NEXT: ret i8 [[FINALRES]] +; %trunc = trunc i128 %arg1 to i8 - %add = add nsw i8 %trunc, 1 + %add = add nsw i8 %trunc, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -194,18 +233,20 @@ define i8 @oneArgPromotionLargerType(i128 %arg1, ptr %base) { ; Use same inserted trunc ; On X86 truncate are free. Check that we are able to promote the add ; to be used as addressing mode and that we insert a truncate for -; *all* the other uses. -; CHECK-LABEL: @oneArgPromotionTruncInsertSeveralUse -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8 -; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, ptr [[GEP]] -; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = add i8 [[LOAD]], [[TRUNC]] -; CHECK: add i8 [[ADDRES]], [[TRUNC]] -; CHECK: ret +; *all* the other uses. define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, ptr %base) { - %add = add nsw i8 %arg1, 1 +; CHECK-LABEL: define i8 @oneArgPromotionTruncInsertSeveralUse( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[PROMOTED:%.*]] = trunc i64 [[ADD]] to i8 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[ALMOSTFINALRES:%.*]] = add i8 [[RES]], [[PROMOTED]] +; CHECK-NEXT: [[FINALRES:%.*]] = add i8 [[ALMOSTFINALRES]], [[PROMOTED]] +; CHECK-NEXT: ret i8 [[FINALRES]] +; + %add = add nsw i8 %arg1, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -216,16 +257,18 @@ define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, ptr %base) { ; Check that the promoted instruction is used for all uses of the original ; sign extension. -; CHECK-LABEL: @oneArgPromotionSExtSeveralUse -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1 -; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, ptr [[GEP]] -; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = zext i8 [[LOAD]] to i64 -; CHECK: add i64 [[ADDRES]], [[PROMOTED]] -; CHECK: ret define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, ptr %base) { - %add = add nsw i8 %arg1, 1 +; CHECK-LABEL: define i64 @oneArgPromotionSExtSeveralUse( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = sext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[ALMOSTFINALRES:%.*]] = zext i8 [[RES]] to i64 +; CHECK-NEXT: [[FINALRES:%.*]] = add i64 [[ALMOSTFINALRES]], [[ADD]] +; CHECK-NEXT: ret i64 [[FINALRES]] +; + %add = add nsw i8 %arg1, 1 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -249,16 +292,19 @@ define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, ptr %base) { ; - Setting the operands of the promoted instruction with the promoted values. ; - Moving instruction around (mainly sext when promoting instruction). ; Each type of those promotions has to be undo at least once during this -; specific test. -; CHECK-LABEL: @twoArgsPromotionNest -; CHECK: [[ORIG:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2 -; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[ORIG]], [[ORIG]] -; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[SEXT]] -; CHECK: ret +; specific test. define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, ptr %base) { +; CHECK-LABEL: define i8 @twoArgsPromotionNest( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTABLEADD1:%.*]] = add nsw i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: [[PROMOTABLEADD2:%.*]] = add nsw i32 [[PROMOTABLEADD1]], [[PROMOTABLEADD1]] +; CHECK-NEXT: [[SEXTADD:%.*]] = sext i32 [[PROMOTABLEADD2]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[SEXTADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %promotableadd1 = add nsw i32 %arg1, %arg2 - %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1 + %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1 %sextadd = sext i32 %promotableadd2 to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -270,18 +316,21 @@ define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, ptr %base) { ; The matcher first promotes the add, removes the trunc and promotes ; the sext of arg1. ; Then, the matcher cannot use an addressing mode r + r + r, thus it -; rolls back. -; CHECK-LABEL: @twoArgsNoPromotionRemove -; CHECK: [[SEXTARG1:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32 -; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[SEXTARG1]] to i8 -; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i8 [[TRUNC]], %arg2 -; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ADD]] to i64 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[SEXT]] -; CHECK: ret +; rolls back. define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, ptr %base) { +; CHECK-LABEL: define i8 @twoArgsNoPromotionRemove( +; CHECK-SAME: i1 [[ARG1:%.*]], i8 [[ARG2:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[SEXTARG1:%.*]] = sext i1 [[ARG1]] to i32 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SEXTARG1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[TRUNC]], [[ARG2]] +; CHECK-NEXT: [[SEXTADD:%.*]] = sext i8 [[ADD]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[SEXTADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = sext i1 %arg1 to i32 %trunc = trunc i32 %sextarg1 to i8 - %add = add nsw i8 %trunc, %arg2 + %add = add nsw i8 %trunc, %arg2 %sextadd = sext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %sextadd %res = load i8, ptr %arrayidx @@ -301,29 +350,40 @@ define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, ptr %base) { ; Check that we did not promote anything in the final matching. ; ; -; CHECK-LABEL: @checkProfitability -; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64 -; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64 -; CHECK: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1 -; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2 -; CHECK: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64 ; BB then -; CHECK: [[BASE1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to ptr -; CHECK: [[FULL1:%[a-zA-Z_0-9-]+]] = getelementptr i8, ptr [[BASE1]], i64 48 -; CHECK: load i32, ptr [[FULL1]] ; BB else -; CHECK: [[BASE2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to ptr -; CHECK: [[FULL2:%[a-zA-Z_0-9-]+]] = getelementptr i8, ptr [[BASE2]], i64 48 -; CHECK: load i32, ptr [[FULL2]] -; CHECK: ret define i32 @checkProfitability(i32 %arg1, i32 %arg2, i1 %test) { +; CHECK-LABEL: define i32 @checkProfitability( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], i1 [[TEST:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[ARG1]], 1 +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[SHL]], [[ARG2]] +; CHECK-NEXT: [[SEXTIDX1:%.*]] = sext i32 [[ADD1]] to i64 +; CHECK-NEXT: br i1 [[TEST]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: [[SUNKADDR:%.*]] = inttoptr i64 [[SEXTIDX1]] to ptr +; CHECK-NEXT: [[SUNKADDR13:%.*]] = getelementptr i8, ptr [[SUNKADDR]], i64 48 +; CHECK-NEXT: [[RES1:%.*]] = load i32, ptr [[SUNKADDR13]], align 4 +; CHECK-NEXT: br label %[[END:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: [[SUNKADDR17:%.*]] = inttoptr i64 [[SEXTIDX1]] to ptr +; CHECK-NEXT: [[SUNKADDR18:%.*]] = getelementptr i8, ptr [[SUNKADDR17]], i64 48 +; CHECK-NEXT: [[RES2:%.*]] = load i32, ptr [[SUNKADDR18]], align 4 +; CHECK-NEXT: br label %[[END]] +; CHECK: [[END]]: +; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[RES1]], %[[THEN]] ], [ [[RES2]], %[[ELSE]] ] +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[SEXTIDX1]] to i32 +; CHECK-NEXT: [[RES:%.*]] = add i32 [[TMP]], [[TMP1]] +; CHECK-NEXT: [[ADDR:%.*]] = inttoptr i32 [[RES]] to ptr +; CHECK-NEXT: [[FINAL:%.*]] = load i32, ptr [[ADDR]], align 4 +; CHECK-NEXT: ret i32 [[FINAL]] +; %shl = shl nsw i32 %arg1, 1 %add1 = add nsw i32 %shl, %arg2 %sextidx1 = sext i32 %add1 to i64 %tmpptr = inttoptr i64 %sextidx1 to ptr %arrayidx1 = getelementptr i32, ptr %tmpptr, i64 12 br i1 %test, label %then, label %else -then: +then: %res1 = load i32, ptr %arrayidx1 br label %end else: @@ -346,15 +406,47 @@ end: ; We used to crash on this function because we did not return the right ; promoted instruction for %conv.i. ; Make sure we generate the right code now. -; CHECK-LABEL: @fn3 ; %conv.i is used twice and only one of its use is being promoted. ; Use it at the starting point for the matching. -; CHECK: %conv.i = zext i16 [[PLAIN_OPND:%[.a-zA-Z_0-9-]+]] to i32 -; CHECK-NEXT: [[PROMOTED_CONV:%[.a-zA-Z_0-9-]+]] = zext i16 [[PLAIN_OPND]] to i64 -; CHECK-NEXT: [[ADD:%[a-zA-Z_0-9-]+]] = getelementptr i8, ptr %P, i64 [[PROMOTED_CONV]] -; CHECK-NEXT: [[ADDR:%[a-zA-Z_0-9-]+]] = getelementptr i8, ptr [[ADD]], i64 7 -; CHECK-NEXT: load i8, ptr [[ADDR]], align 1 define signext i16 @fn3(ptr nocapture readonly %P) { +; CHECK-LABEL: define signext i16 @fn3( +; CHECK-SAME: ptr nocapture readonly [[P:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[WHILE_BODY_I_I:.*]] +; CHECK: [[WHILE_BODY_I_I]]: +; CHECK-NEXT: [[SRC_ADDR_0_I_I:%.*]] = phi i16 [ 0, %[[ENTRY]] ], [ [[INC_I_I:%.*]], %[[WHILE_BODY_I_I]] ] +; CHECK-NEXT: [[INC_I_I]] = add i16 [[SRC_ADDR_0_I_I]], 1 +; CHECK-NEXT: [[IDXPROM_I_I:%.*]] = sext i16 [[SRC_ADDR_0_I_I]] to i64 +; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[IDXPROM_I_I]] +; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr inbounds i8, ptr [[SUNKADDR]], i64 8 +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[SUNKADDR2]], align 1 +; CHECK-NEXT: [[CONV2_I_I:%.*]] = zext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[AND_I_I:%.*]] = and i32 [[CONV2_I_I]], 15 +; CHECK-NEXT: store i32 [[AND_I_I]], ptr @a, align 4 +; CHECK-NEXT: [[TOBOOL_I_I:%.*]] = icmp eq i32 [[AND_I_I]], 0 +; CHECK-NEXT: br i1 [[TOBOOL_I_I]], label %[[WHILE_BODY_I_I]], label %[[FN1_EXIT_I:.*]] +; CHECK: [[FN1_EXIT_I]]: +; CHECK-NEXT: [[CONV_I:%.*]] = zext i16 [[INC_I_I]] to i32 +; CHECK-NEXT: [[PROMOTED4:%.*]] = zext i16 [[INC_I_I]] to i64 +; CHECK-NEXT: [[SUNKADDR5:%.*]] = getelementptr i8, ptr [[P]], i64 [[PROMOTED4]] +; CHECK-NEXT: [[SUNKADDR6:%.*]] = getelementptr i8, ptr [[SUNKADDR5]], i64 7 +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[SUNKADDR6]], align 1 +; CHECK-NEXT: [[CONV2_I:%.*]] = sext i8 [[TMP2]] to i16 +; CHECK-NEXT: store i16 [[CONV2_I]], ptr @b, align 2 +; CHECK-NEXT: [[SUB4_I:%.*]] = sub nsw i32 0, [[CONV_I]] +; CHECK-NEXT: [[CONV5_I:%.*]] = zext i16 [[CONV2_I]] to i32 +; CHECK-NEXT: [[CMP_I:%.*]] = icmp sgt i32 [[CONV5_I]], [[SUB4_I]] +; CHECK-NEXT: br i1 [[CMP_I]], label %[[IF_THEN_I:.*]], label %[[FN2_EXIT:.*]] +; CHECK: [[IF_THEN_I]]: +; CHECK-NEXT: [[END_I:%.*]] = getelementptr inbounds [[STRUCT_DNS_PACKET:%.*]], ptr [[P]], i64 0, i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[END_I]], align 4 +; CHECK-NEXT: [[SUB7_I:%.*]] = add i32 [[TMP3]], 65535 +; CHECK-NEXT: [[CONV8_I:%.*]] = trunc i32 [[SUB7_I]] to i16 +; CHECK-NEXT: br label %[[FN2_EXIT]] +; CHECK: [[FN2_EXIT]]: +; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i16 [ [[CONV8_I]], %[[IF_THEN_I]] ], [ undef, %[[FN1_EXIT_I]] ] +; CHECK-NEXT: ret i16 [[RETVAL_0_I]] +; entry: %tmp = getelementptr inbounds %struct.dns_packet, ptr %P, i64 0, i32 2 br label %while.body.i.i @@ -399,13 +491,16 @@ fn2.exit: ; preds = %if.then.i, %fn1.exi ; Check that we do not promote an extension if the non-wrapping flag does not ; match the kind of the extension. -; CHECK-LABEL: @noPromotionFlag -; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = zext i32 [[ADD]] to i64 -; CHECK: inttoptr i64 [[PROMOTED]] to ptr -; CHECK: ret define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) { - %add = add nsw i32 %arg1, %arg2 +; CHECK-LABEL: define i8 @noPromotionFlag( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: [[ZEXTADD:%.*]] = zext i32 [[ADD]] to i64 +; CHECK-NEXT: [[BASE:%.*]] = inttoptr i64 [[ZEXTADD]] to ptr +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[BASE]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nsw i32 %arg1, %arg2 %zextadd = zext i32 %add to i64 %base = inttoptr i64 %zextadd to ptr %res = load i8, ptr %base @@ -413,14 +508,17 @@ define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) { } ; Check that we correctly promote both operands of the promotable add with zext. -; CHECK-LABEL: @twoArgsPromotionZExt -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg1 to i64 -; CHECK: [[ARG2ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg2 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], [[ARG2ZEXT]] -; CHECK: inttoptr i64 [[PROMOTED]] to ptr -; CHECK: ret define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) { - %add = add nuw i32 %arg1, %arg2 +; CHECK-LABEL: define i8 @twoArgsPromotionZExt( +; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = zext i32 [[ARG1]] to i64 +; CHECK-NEXT: [[PROMOTED2:%.*]] = zext i32 [[ARG2]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED]], [[PROMOTED2]] +; CHECK-NEXT: [[BASE:%.*]] = inttoptr i64 [[ADD]] to ptr +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[BASE]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nuw i32 %arg1, %arg2 %zextadd = zext i32 %add to i64 %base = inttoptr i64 %zextadd to ptr %res = load i8, ptr %base @@ -428,13 +526,16 @@ define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) { } ; Check that we correctly promote constant arguments. -; CHECK-LABEL: @oneArgPromotionNegativeCstZExt -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 255 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, ptr %base) { - %add = add nuw i8 %arg1, -1 +; CHECK-LABEL: define i8 @oneArgPromotionNegativeCstZExt( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED:%.*]] = zext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED]], 255 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; + %add = add nuw i8 %arg1, -1 %zextadd = zext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %zextadd %res = load i8, ptr %arrayidx @@ -442,14 +543,17 @@ define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, ptr %base) { } ; Check that we are able to merge two zero extensions. -; CHECK-LABEL: @oneArgPromotionZExtZExt -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionZExtZExt(i8 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionZExtZExt( +; CHECK-SAME: i8 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED2:%.*]] = zext i8 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %zext = zext i8 %arg1 to i32 - %add = add nuw i32 %zext, 1 + %add = add nuw i32 %zext, 1 %zextadd = zext i32 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %zextadd %res = load i8, ptr %arrayidx @@ -458,17 +562,20 @@ define i8 @oneArgPromotionZExtZExt(i8 %arg1, ptr %base) { ; Check that we do not promote truncate when the dropped bits ; are of a different kind. -; CHECK-LABEL: @oneArgPromotionBlockTruncZExt -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32 -; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8 -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1TRUNC]] to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionBlockTruncZExt( +; CHECK-SAME: i1 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[SEXTARG1:%.*]] = sext i1 [[ARG1]] to i32 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SEXTARG1]] to i8 +; CHECK-NEXT: [[PROMOTED:%.*]] = zext i8 [[TRUNC]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = sext i1 %arg1 to i32 %trunc = trunc i32 %sextarg1 to i8 - %add = add nuw i8 %trunc, 1 + %add = add nuw i8 %trunc, 1 %zextadd = zext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %zextadd %res = load i8, ptr %arrayidx @@ -477,15 +584,18 @@ define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, ptr %base) { ; Check that we are able to promote truncate when we know all the bits ; that are dropped. -; CHECK-LABEL: @oneArgPromotionPassTruncZExt -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i1 %arg1 to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionPassTruncZExt( +; CHECK-SAME: i1 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[PROMOTED2:%.*]] = zext i1 [[ARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED2]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = zext i1 %arg1 to i32 %trunc = trunc i32 %sextarg1 to i8 - %add = add nuw i8 %trunc, 1 + %add = add nuw i8 %trunc, 1 %zextadd = zext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %zextadd %res = load i8, ptr %arrayidx @@ -493,15 +603,18 @@ define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, ptr %base) { } ; Check that we do not promote sext with zext. -; CHECK-LABEL: @oneArgPromotionBlockSExtZExt -; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i8 -; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1SEXT]] to i64 -; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1 -; CHECK: getelementptr inbounds i8, ptr %base, i64 [[PROMOTED]] -; CHECK: ret define i8 @oneArgPromotionBlockSExtZExt(i1 %arg1, ptr %base) { +; CHECK-LABEL: define i8 @oneArgPromotionBlockSExtZExt( +; CHECK-SAME: i1 [[ARG1:%.*]], ptr [[BASE:%.*]]) { +; CHECK-NEXT: [[SEXTARG1:%.*]] = sext i1 [[ARG1]] to i8 +; CHECK-NEXT: [[PROMOTED:%.*]] = zext i8 [[SEXTARG1]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[PROMOTED]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD]] +; CHECK-NEXT: [[RES:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: ret i8 [[RES]] +; %sextarg1 = sext i1 %arg1 to i8 - %add = add nuw i8 %sextarg1, 1 + %add = add nuw i8 %sextarg1, 1 %zextadd = zext i8 %add to i64 %arrayidx = getelementptr inbounds i8, ptr %base, i64 %zextadd %res = load i8, ptr %arrayidx From 1c067a513c757b731434fd793351c52b49628489 Mon Sep 17 00:00:00 2001 From: William Moses Date: Wed, 8 Jan 2025 07:40:05 -0500 Subject: [PATCH 008/163] [MLIR] Enable import of non self referential alias scopes (#121987) Fixes #121965. --------- Co-authored-by: Christian Ulmann Co-authored-by: Alex Zinenko --- .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 8 ++- mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp | 17 +++++++ mlir/lib/Target/LLVMIR/ModuleImport.cpp | 28 +++++++--- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 19 +++++-- mlir/test/Dialect/LLVMIR/roundtrip.mlir | 10 ++++ .../LLVMIR/Import/metadata-alias-scopes.ll | 35 +++++++++++++ .../Target/LLVMIR/attribute-alias-scopes.mlir | 51 +++++++++++++++++++ 7 files changed, 156 insertions(+), 12 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index e8eeafd09a9cb..267389774bd5a 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -825,7 +825,7 @@ def LLVM_MemoryEffectsAttr : LLVM_Attr<"MemoryEffects", "memory_effects"> { def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain", "alias_scope_domain"> { let parameters = (ins - "DistinctAttr":$id, + "Attribute":$id, OptionalParameter<"StringAttr">:$description ); @@ -853,7 +853,7 @@ def LLVM_AliasScopeDomainAttr : LLVM_Attr<"AliasScopeDomain", def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> { let parameters = (ins - "DistinctAttr":$id, + "Attribute":$id, "AliasScopeDomainAttr":$domain, OptionalParameter<"StringAttr">:$description ); @@ -891,6 +891,8 @@ def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> { } ``` + The first attribute can either be a DistinctAttr or a StringAttr. + See the following link for more details: https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata }]; @@ -898,6 +900,8 @@ def LLVM_AliasScopeAttr : LLVM_Attr<"AliasScope", "alias_scope"> { let summary = "LLVM dialect alias scope"; let assemblyFormat = "`<` struct(params) `>`"; + + let genVerifyDecl = 1; } def LLVM_AliasScopeArrayAttr diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp index 7490e8735f5fd..ff1636bc121b6 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -52,6 +52,23 @@ void LLVMDialect::registerAttributes() { >(); } +//===----------------------------------------------------------------------===// +// AliasScopeAttr +//===----------------------------------------------------------------------===// + +LogicalResult +AliasScopeAttr::verify(function_ref emitError, + Attribute id, AliasScopeDomainAttr domain, + StringAttr description) { + (void)domain; + (void)description; + if (!llvm::isa(id)) + return emitError() + << "id of an alias scope must be a StringAttr or a DistrinctAttr"; + + return success(); +} + //===----------------------------------------------------------------------===// // DINodeAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 95fb673fc72e3..2d8d7745eca9b 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -427,19 +427,33 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) { return node->getNumOperands() != 0 && node == dyn_cast(node->getOperand(0)); }; + auto verifySelfRefOrString = [](const llvm::MDNode *node) { + return node->getNumOperands() != 0 && + (node == dyn_cast(node->getOperand(0)) || + isa(node->getOperand(0))); + }; // Helper that verifies the given operand is a string or does not exist. auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) { return idx >= node->getNumOperands() || isa(node->getOperand(idx)); }; + + auto getIdAttr = [&](const llvm::MDNode *node) -> Attribute { + if (verifySelfRef(node)) + return DistinctAttr::create(builder.getUnitAttr()); + + auto name = cast(node->getOperand(0)); + return builder.getStringAttr(name->getString()); + }; + // Helper that creates an alias scope domain attribute. auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) { StringAttr description = nullptr; if (aliasDomain->getNumOperands() >= 2) if (auto *operand = dyn_cast(aliasDomain->getOperand(1))) description = builder.getStringAttr(operand->getString()); - return builder.getAttr( - DistinctAttr::create(builder.getUnitAttr()), description); + Attribute idAttr = getIdAttr(aliasDomain); + return builder.getAttr(idAttr, description); }; // Collect the alias scopes and domains to translate them. @@ -452,10 +466,11 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) { // verifying its domain. Perform the verification before looking it up in // the alias scope mapping since it could have been inserted as a domain // node before. - if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2)) + if (!verifySelfRefOrString(scope) || !domain || + !verifyDescription(scope, 2)) return emitError(loc) << "unsupported alias scope node: " << diagMD(scope, llvmModule.get()); - if (!verifySelfRef(domain) || !verifyDescription(domain, 1)) + if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1)) return emitError(loc) << "unsupported alias domain node: " << diagMD(domain, llvmModule.get()); @@ -473,9 +488,10 @@ ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) { StringAttr description = nullptr; if (!aliasScope.getName().empty()) description = builder.getStringAttr(aliasScope.getName()); + Attribute idAttr = getIdAttr(scope); auto aliasScopeOp = builder.getAttr( - DistinctAttr::create(builder.getUnitAttr()), - cast(it->second), description); + idAttr, cast(it->second), description); + aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp); } } diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index ad62ae0cef57b..4367100e3aca6 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1724,25 +1724,36 @@ ModuleTranslation::getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr) { aliasScopeAttr.getDomain(), nullptr); if (insertedDomain) { llvm::SmallVector operands; - // Placeholder for self-reference. + // Placeholder for potential self-reference. operands.push_back(dummy.get()); if (StringAttr description = aliasScopeAttr.getDomain().getDescription()) operands.push_back(llvm::MDString::get(ctx, description)); domainIt->second = llvm::MDNode::get(ctx, operands); // Self-reference for uniqueness. - domainIt->second->replaceOperandWith(0, domainIt->second); + llvm::Metadata *replacement; + if (auto stringAttr = + dyn_cast(aliasScopeAttr.getDomain().getId())) + replacement = llvm::MDString::get(ctx, stringAttr.getValue()); + else + replacement = domainIt->second; + domainIt->second->replaceOperandWith(0, replacement); } // Convert the scope metadata node. assert(domainIt->second && "Scope's domain should already be valid"); llvm::SmallVector operands; - // Placeholder for self-reference. + // Placeholder for potential self-reference. operands.push_back(dummy.get()); operands.push_back(domainIt->second); if (StringAttr description = aliasScopeAttr.getDescription()) operands.push_back(llvm::MDString::get(ctx, description)); scopeIt->second = llvm::MDNode::get(ctx, operands); // Self-reference for uniqueness. - scopeIt->second->replaceOperandWith(0, scopeIt->second); + llvm::Metadata *replacement; + if (auto stringAttr = dyn_cast(aliasScopeAttr.getId())) + replacement = llvm::MDString::get(ctx, stringAttr.getValue()); + else + replacement = scopeIt->second; + scopeIt->second->replaceOperandWith(0, replacement); return scopeIt->second; } diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index aebfd7492093c..88660ce598f3c 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -750,6 +750,16 @@ llvm.func @experimental_noalias_scope_decl() { llvm.return } +#alias_scope_domain2 = #llvm.alias_scope_domain +#alias_scope2 = #llvm.alias_scope + +// CHECK-LABEL: @experimental_noalias_scope_with_string_id +llvm.func @experimental_noalias_scope_with_string_id() { + // CHECK: llvm.intr.experimental.noalias.scope.decl #{{.*}} + llvm.intr.experimental.noalias.scope.decl #alias_scope2 + llvm.return +} + // CHECK-LABEL: @experimental_constrained_fptrunc llvm.func @experimental_constrained_fptrunc(%in: f64) { // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} towardzero ignore : f64 to f32 diff --git a/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll index f5128ff76bc5f..bf4c85786216f 100644 --- a/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll +++ b/mlir/test/Target/LLVMIR/Import/metadata-alias-scopes.ll @@ -92,3 +92,38 @@ declare void @foo(ptr %arg1) !0 = distinct !{!0, !"The domain"} !1 = !{!1, !0} !2 = !{!1} + +; // ----- + +; CHECK: #[[DOMAIN:.*]] = #llvm.alias_scope_domain +; CHECK: #[[$SCOPE0:.*]] = #llvm.alias_scope +; CHECK: #[[$SCOPE1:.*]] = #llvm.alias_scope +; CHECK: #[[$SCOPE2:.*]] = #llvm.alias_scope + +; CHECK-LABEL: llvm.func @alias_scope +define void @alias_scope(ptr %arg1) { + ; CHECK: llvm.load + ; CHECK-SAME: alias_scopes = [#[[$SCOPE0]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE1]], #[[$SCOPE2]]] + %1 = load i32, ptr %arg1, !alias.scope !4, !noalias !7 + ; CHECK: llvm.load + ; CHECK-SAME: alias_scopes = [#[[$SCOPE1]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE2]]] + %2 = load i32, ptr %arg1, !alias.scope !5, !noalias !8 + ; CHECK: llvm.load + ; CHECK-SAME: alias_scopes = [#[[$SCOPE2]]] + ; CHECK-SAME: noalias_scopes = [#[[$SCOPE0]], #[[$SCOPE1]]] + %3 = load i32, ptr %arg1, !alias.scope !6, !noalias !9 + ret void +} + +!0 = !{!"domain1"} +!1 = !{!"scopeid1", !0, !"The first scope"} +!2 = !{!"scopeid2", !0} +!3 = !{!"scopeid3", !0} +!4 = !{!1} +!5 = !{!2} +!6 = !{!3} +!7 = !{!2, !3} +!8 = !{!1, !3} +!9 = !{!1, !2} diff --git a/mlir/test/Target/LLVMIR/attribute-alias-scopes.mlir b/mlir/test/Target/LLVMIR/attribute-alias-scopes.mlir index fa3395533af22..fb71a51512aee 100644 --- a/mlir/test/Target/LLVMIR/attribute-alias-scopes.mlir +++ b/mlir/test/Target/LLVMIR/attribute-alias-scopes.mlir @@ -104,3 +104,54 @@ llvm.func @self_reference() { // CHECK-DAG: ![[SCOPES]] = !{![[SCOPE]]} // CHECK-DAG: = !DISubroutineType(types: ![[TYPES:[0-9]+]]) // CHECK-DAG: ![[TYPES]] = !{null} + +// ----- + +llvm.func @foo(%arg0: !llvm.ptr) + +#alias_scope_domain = #llvm.alias_scope_domain +#alias_scope1 = #llvm.alias_scope +#alias_scope2 = #llvm.alias_scope +#alias_scope3 = #llvm.alias_scope + +// CHECK-LABEL: @alias_scopes +llvm.func @alias_scopes(%arg1 : !llvm.ptr) { + %0 = llvm.mlir.constant(0 : i32) : i32 + // CHECK: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPES1:[0-9]+]]) + llvm.intr.experimental.noalias.scope.decl #alias_scope1 + // CHECK: store {{.*}}, !alias.scope ![[SCOPES1]], !noalias ![[SCOPES23:[0-9]+]] + llvm.store %0, %arg1 {alias_scopes = [#alias_scope1], noalias_scopes = [#alias_scope2, #alias_scope3]} : i32, !llvm.ptr + // CHECK: load {{.*}}, !alias.scope ![[SCOPES2:[0-9]+]], !noalias ![[SCOPES13:[0-9]+]] + %1 = llvm.load %arg1 {alias_scopes = [#alias_scope2], noalias_scopes = [#alias_scope1, #alias_scope3]} : !llvm.ptr -> i32 + // CHECK: atomicrmw {{.*}}, !alias.scope ![[SCOPES3:[0-9]+]], !noalias ![[SCOPES12:[0-9]+]] + %2 = llvm.atomicrmw add %arg1, %0 monotonic {alias_scopes = [#alias_scope3], noalias_scopes = [#alias_scope1, #alias_scope2]} : !llvm.ptr, i32 + // CHECK: cmpxchg {{.*}}, !alias.scope ![[SCOPES3]] + %3 = llvm.cmpxchg %arg1, %1, %2 acq_rel monotonic {alias_scopes = [#alias_scope3]} : !llvm.ptr, i32 + %5 = llvm.mlir.constant(42 : i8) : i8 + // CHECK: llvm.memcpy{{.*}}, !alias.scope ![[SCOPES3]] + "llvm.intr.memcpy"(%arg1, %arg1, %0) <{isVolatile = false}> {alias_scopes = [#alias_scope3]} : (!llvm.ptr, !llvm.ptr, i32) -> () + // CHECK: llvm.memset{{.*}}, !noalias ![[SCOPES3]] + "llvm.intr.memset"(%arg1, %5, %0) <{isVolatile = false}> {noalias_scopes = [#alias_scope3]} : (!llvm.ptr, i8, i32) -> () + // CHECK: call void @foo({{.*}} !alias.scope ![[SCOPES3]] + llvm.call @foo(%arg1) {alias_scopes = [#alias_scope3]} : (!llvm.ptr) -> () + // CHECK: call void @foo({{.*}} !noalias ![[SCOPES3]] + llvm.call @foo(%arg1) {noalias_scopes = [#alias_scope3]} : (!llvm.ptr) -> () + llvm.return +} + +// Check the intrinsic declarations. +// CHECK-DAG: declare void @llvm.experimental.noalias.scope.decl(metadata) +// CHECK-DAG: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) +// CHECK-DAG: declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) + +// Check the translated metadata. +// CHECK-DAG: ![[DOMAIN:[0-9]+]] = !{!"domain1", !"The domain"} +// CHECK-DAG: ![[SCOPE1:[0-9]+]] = !{!"scope1", ![[DOMAIN]], !"The first scope"} +// CHECK-DAG: ![[SCOPE2:[0-9]+]] = !{!"scope2", ![[DOMAIN]]} +// CHECK-DAG: ![[SCOPE3:[0-9]+]] = !{!"scope3", ![[DOMAIN]]} +// CHECK-DAG: ![[SCOPES1]] = !{![[SCOPE1]]} +// CHECK-DAG: ![[SCOPES2]] = !{![[SCOPE2]]} +// CHECK-DAG: ![[SCOPES3]] = !{![[SCOPE3]]} +// CHECK-DAG: ![[SCOPES12]] = !{![[SCOPE1]], ![[SCOPE2]]} +// CHECK-DAG: ![[SCOPES13]] = !{![[SCOPE1]], ![[SCOPE3]]} +// CHECK-DAG: ![[SCOPES23]] = !{![[SCOPE2]], ![[SCOPE3]]} From 51d7605df9647f54d702df1f7d4029e95dce7156 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 8 Jan 2025 13:43:17 +0100 Subject: [PATCH 009/163] Fix macho-merged-funcs-dwarf.yaml test on Windows --- .../ARM_AArch64/macho-merged-funcs-dwarf.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/tools/llvm-gsymutil/ARM_AArch64/macho-merged-funcs-dwarf.yaml b/llvm/test/tools/llvm-gsymutil/ARM_AArch64/macho-merged-funcs-dwarf.yaml index 97dfc61ce1e1d..522c576854421 100644 --- a/llvm/test/tools/llvm-gsymutil/ARM_AArch64/macho-merged-funcs-dwarf.yaml +++ b/llvm/test/tools/llvm-gsymutil/ARM_AArch64/macho-merged-funcs-dwarf.yaml @@ -71,11 +71,11 @@ #### TODO: Fix non-determinism leading that is currently worked around with `{{[1-3]}}` below. # CHECK-MERGED-LOOKUP: Found 3 functions at address 0x0000000000000248: -# CHECK-MERGED-LOOKUP-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml/out/file_0{{[1-3]}}.cpp:5 -# CHECK-MERGED-LOOKUP-NEXT-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml/out/file_0{{[1-3]}}.cpp:5 -# CHECK-MERGED-LOOKUP-NEXT-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml/out/file_0{{[1-3]}}.cpp:5 +# CHECK-MERGED-LOOKUP-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml{{[/\\]}}out/file_0{{[1-3]}}.cpp:5 +# CHECK-MERGED-LOOKUP-NEXT-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml{{[/\\]}}out/file_0{{[1-3]}}.cpp:5 +# CHECK-MERGED-LOOKUP-NEXT-NEXT: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml{{[/\\]}}out/file_0{{[1-3]}}.cpp:5 -# CHECK-NORMAL-LOOKUP: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml/out/file_0{{[1-3]}}.cpp:5 +# CHECK-NORMAL-LOOKUP: 0x0000000000000248: my_func_0{{[1-3]}} @ /tmp/test_gsym_yaml{{[/\\]}}out/file_0{{[1-3]}}.cpp:5 --- !mach-o From 72b6a573639fe85eb121c66e47b2c9e6ea64df5e Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Wed, 8 Jan 2025 20:56:49 +0800 Subject: [PATCH 010/163] [clang-tidy] fix false positives when using name-independent variables after C++26 for bugprone-unused-local-non-trivial-variable (#121783) Fixed: #121731 According to https://eel.is/c++draft/basic.scope.scope#5, name independent declaration should not be warned as unused --- .../UnusedLocalNonTrivialVariableCheck.cpp | 8 ++++++- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++ .../unused-local-non-trivial-variable.rst | 1 + ...non-trivial-variable-name-independence.cpp | 21 +++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp index 37baae7a6f0c3..f15fd4d9ad9fa 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp @@ -29,6 +29,12 @@ static constexpr StringRef DefaultIncludeTypeRegex = AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); } AST_MATCHER(VarDecl, isReferenced) { return Node.isReferenced(); } +AST_MATCHER_P(VarDecl, explicitMarkUnused, LangOptions, LangOpts) { + // Implementations should not emit a warning that a name-independent + // declaration is used or unused. + return Node.hasAttr() || + (LangOpts.CPlusPlus26 && Node.isPlaceholderVar(LangOpts)); +} AST_MATCHER(Type, isReferenceType) { return Node.isReferenceType(); } AST_MATCHER(QualType, isTrivial) { return Node.isTrivialType(Finder->getASTContext()) || @@ -60,7 +66,7 @@ void UnusedLocalNonTrivialVariableCheck::registerMatchers(MatchFinder *Finder) { varDecl(isLocalVarDecl(), unless(isReferenced()), unless(isExceptionVariable()), hasLocalStorage(), isDefinition(), unless(hasType(isReferenceType())), unless(hasType(isTrivial())), - unless(hasAttr(attr::Kind::Unused)), + unless(explicitMarkUnused(getLangOpts())), hasType(hasUnqualifiedDesugaredType( anyOf(recordType(hasDeclaration(namedDecl( matchesAnyListedName(IncludeTypes), diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 35cb3e387e4e6..94e15639c4a92 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -241,6 +241,10 @@ Changes in existing checks ` check to allow specifying additional functions to match. +- Improved :doc:`bugprone-unused-local-non-trivial-variable + ` check to avoid + false positives when using name-independent variables after C++26. + - Improved :doc:`bugprone-use-after-move ` to avoid triggering on ``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects, diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst index 9f283de78fbde..672eab62b4af6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst @@ -12,6 +12,7 @@ The following types of variables are excluded from this check: * static or thread local * structured bindings * variables with ``[[maybe_unused]]`` attribute +* name-independent variables This check can be configured to warn on all non-trivial variables by setting `IncludeTypes` to `.*`, and excluding specific types using `ExcludeTypes`. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp new file mode 100644 index 0000000000000..bcc8b810acabf --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp @@ -0,0 +1,21 @@ +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=,CXX23 %s bugprone-unused-local-non-trivial-variable %t -- \ +// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \ +// RUN: -- +// RUN: %check_clang_tidy -std=c++26 %s bugprone-unused-local-non-trivial-variable %t -- \ +// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \ +// RUN: -- + +namespace async { +class Foo { + public: + ~Foo(); + private: +}; +} // namespace async + +void check() { + async::Foo C; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unused local variable 'C' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable] + async::Foo _; + // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: unused local variable '_' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable] +} From 645c1ee8969cb79f6fad478944a1a6ccaa47aed6 Mon Sep 17 00:00:00 2001 From: jeanPerier Date: Wed, 8 Jan 2025 14:17:04 +0100 Subject: [PATCH 011/163] [flang][driver] add option to make all main program variable static (#121968) Co-authored-by: Kiran Chandramohan --- clang/include/clang/Driver/Options.td | 3 +++ clang/lib/Driver/ToolChains/Flang.cpp | 3 ++- flang/lib/Frontend/CompilerInvocation.cpp | 5 +++++ flang/test/Driver/fsave-main-program.f90 | 5 +++++ flang/test/Lower/fsave-main-program.f90 | 10 ++++++++++ 5 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 flang/test/Driver/fsave-main-program.f90 create mode 100644 flang/test/Lower/fsave-main-program.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0528104f05515..52823430919de 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6945,6 +6945,9 @@ defm unsigned : OptInFC1FFlag<"unsigned", "Enables UNSIGNED type">; def fno_automatic : Flag<["-"], "fno-automatic">, Group, HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; +def fsave_main_program : Flag<["-"], "fsave-main-program">, Group, + HelpText<"Place all variables from the main program in static memory (otherwise scalars may be placed on the stack)">; + defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", PosFlag, NegFlag>; diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 7034e5b475c1d..75b10e88371ae 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -57,7 +57,8 @@ void Flang::addFortranDialectOptions(const ArgList &Args, options::OPT_fno_automatic, options::OPT_fhermetic_module_files, options::OPT_frealloc_lhs, - options::OPT_fno_realloc_lhs}); + options::OPT_fno_realloc_lhs, + options::OPT_fsave_main_program}); } void Flang::addPreprocessingOptions(const ArgList &Args, diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 79386c92d552c..340efb1c63a5e 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -766,6 +766,11 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave); } + // -fsave-main-program + if (args.hasArg(clang::driver::options::OPT_fsave_main_program)) { + opts.features.Enable(Fortran::common::LanguageFeature::SaveMainProgram); + } + if (args.hasArg( clang::driver::options::OPT_falternative_parameter_statement)) { opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter); diff --git a/flang/test/Driver/fsave-main-program.f90 b/flang/test/Driver/fsave-main-program.f90 new file mode 100644 index 0000000000000..bffdfd97911e8 --- /dev/null +++ b/flang/test/Driver/fsave-main-program.f90 @@ -0,0 +1,5 @@ +! Check that the driver passes through -fsave-main-program: +! RUN: %flang -### -S -fsave-main-program %s -o - 2>&1 | FileCheck %s +! Check that the compiler accepts -fsave-main-program: +! RUN: %flang_fc1 -emit-hlfir -fsave-main-program %s -o - +! CHECK: "-fc1"{{.*}}"-fsave-main-program" diff --git a/flang/test/Lower/fsave-main-program.f90 b/flang/test/Lower/fsave-main-program.f90 new file mode 100644 index 0000000000000..17fc1b02f5068 --- /dev/null +++ b/flang/test/Lower/fsave-main-program.f90 @@ -0,0 +1,10 @@ +! Test -fsave-main-program switch. +! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck --check-prefix=CHECK-DEFAULT %s +! RUN: %flang_fc1 -fsave-main-program -emit-hlfir -o - %s | FileCheck --check-prefix=CHECK-SAVE %s +program test +integer :: i +call foo(i) +end + +!CHECK-DEFAULT-NOT: fir.global internal @_QFEi +!CHECK-SAVE: fir.global internal @_QFEi From 7004d6815b3a0c6d9c15a19b6927746a97564ba7 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 8 Jan 2025 13:22:09 +0000 Subject: [PATCH 012/163] [compiler-rt][rtsan] adding setlinebuf/setbuffer interception. (#122018) catering to platform differences as those calls are not posix. --- .../lib/rtsan/rtsan_interceptors_posix.cpp | 24 +++++++++++++++++ .../tests/rtsan_test_interceptors_posix.cpp | 26 +++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 7ec0382b58566..6a5f4b91d11d7 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -347,11 +347,33 @@ INTERCEPTOR(int, setvbuf, FILE *stream, char *buf, int mode, size_t size) { __rtsan_notify_intercepted_call("setvbuf"); return REAL(setvbuf)(stream, buf, mode, size); } + +#if SANITIZER_LINUX +INTERCEPTOR(void, setlinebuf, FILE *stream) { +#else +INTERCEPTOR(int, setlinebuf, FILE *stream) { +#endif + __rtsan_notify_intercepted_call("setlinebuf"); + return REAL(setlinebuf)(stream); +} + +#if SANITIZER_LINUX +INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, size_t size) { +#else +INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, int size) { +#endif + __rtsan_notify_intercepted_call("setbuffer"); + return REAL(setbuffer)(stream, buf, size); +} #define RTSAN_MAYBE_INTERCEPT_SETBUF INTERCEPT_FUNCTION(setbuf) #define RTSAN_MAYBE_INTERCEPT_SETVBUF INTERCEPT_FUNCTION(setvbuf) +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF INTERCEPT_FUNCTION(setlinebuf) +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER INTERCEPT_FUNCTION(setbuffer) #else #define RTSAN_MAYBE_INTERCEPT_SETBUF #define RTSAN_MAYBE_INTERCEPT_SETVBUF +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER #endif INTERCEPTOR(int, puts, const char *s) { @@ -1018,6 +1040,8 @@ void __rtsan::InitializeInterceptors() { RTSAN_MAYBE_INTERCEPT_FMEMOPEN; RTSAN_MAYBE_INTERCEPT_SETBUF; RTSAN_MAYBE_INTERCEPT_SETVBUF; + RTSAN_MAYBE_INTERCEPT_SETLINEBUF; + RTSAN_MAYBE_INTERCEPT_SETBUFFER; INTERCEPT_FUNCTION(lseek); RTSAN_MAYBE_INTERCEPT_LSEEK64; INTERCEPT_FUNCTION(dup); diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index db0ec951ad10c..5488d3c7e2056 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -409,7 +409,7 @@ TEST_F(RtsanFileTest, SetbufDieWhenRealtime) { FILE *f = fopen(GetTemporaryFilePath(), "w"); EXPECT_THAT(f, Ne(nullptr)); - auto Func = [&f, &buffer]() { setbuf(f, buffer); }; + auto Func = [f, &buffer]() { setbuf(f, buffer); }; ExpectRealtimeDeath(Func, "setbuf"); ExpectNonRealtimeSurvival(Func); @@ -421,7 +421,7 @@ TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { FILE *f = fopen(GetTemporaryFilePath(), "w"); EXPECT_THAT(f, Ne(nullptr)); - auto Func = [&f, &buffer, &size]() { + auto Func = [f, &buffer, size]() { int r = setvbuf(f, buffer, _IOFBF, size); EXPECT_THAT(r, Eq(0)); }; @@ -429,6 +429,28 @@ TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { ExpectRealtimeDeath(Func, "setvbuf"); ExpectNonRealtimeSurvival(Func); } + +TEST_F(RtsanFileTest, SetlinebufDieWhenRealtime) { + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [f]() { setlinebuf(f); }; + + ExpectRealtimeDeath(Func, "setlinebuf"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) { + char buffer[1024]; + size_t size = sizeof(buffer); + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [f, &buffer, size]() { setbuffer(f, buffer, size); }; + + ExpectRealtimeDeath(Func, "setbuffer"); + ExpectNonRealtimeSurvival(Func); +} #endif class RtsanOpenedFileTest : public RtsanFileTest { From d07762e47419a1ef892729a420d0c4769b6702a7 Mon Sep 17 00:00:00 2001 From: Jessica Del <50999226+OutOfCache@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:24:39 +0100 Subject: [PATCH 013/163] [UpdateTestChecks][NFC] - Fix typos (#121964) substition -> substitution in-betweem -> in-between --- llvm/test/tools/UpdateTestChecks/lit.local.cfg | 16 ++++++++-------- llvm/utils/UpdateTestChecks/common.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/llvm/test/tools/UpdateTestChecks/lit.local.cfg b/llvm/test/tools/UpdateTestChecks/lit.local.cfg index a954eb7ba1740..7147769502a6f 100644 --- a/llvm/test/tools/UpdateTestChecks/lit.local.cfg +++ b/llvm/test/tools/UpdateTestChecks/lit.local.cfg @@ -10,7 +10,7 @@ except ImportError: from pipes import quote as shell_quote -def add_update_script_substition( +def add_update_script_substitution( name, python_exe=config.python_executable, extra_args="" ): assert name.startswith("%") @@ -33,26 +33,26 @@ llc_path = os.path.join(config.llvm_tools_dir, "llc") if os.path.isfile(llc_path): config.available_features.add("llc-binary") llc_arg = "--llc-binary " + shell_quote(llc_path) - add_update_script_substition("%update_llc_test_checks", extra_args=llc_arg) - add_update_script_substition("%update_mir_test_checks", extra_args=llc_arg) + add_update_script_substitution("%update_llc_test_checks", extra_args=llc_arg) + add_update_script_substitution("%update_mir_test_checks", extra_args=llc_arg) opt_path = os.path.join(config.llvm_tools_dir, "opt") if os.path.isfile(opt_path): config.available_features.add("opt-binary") opt_arg = "--opt-binary " + shell_quote(opt_path) - add_update_script_substition("%update_test_checks", extra_args=opt_arg) - add_update_script_substition("%update_analyze_test_checks", extra_args=opt_arg) + add_update_script_substitution("%update_test_checks", extra_args=opt_arg) + add_update_script_substitution("%update_analyze_test_checks", extra_args=opt_arg) llvm_mca_path = os.path.join(config.llvm_tools_dir, "llvm-mca") if os.path.isfile(llvm_mca_path): config.available_features.add("llvm-mca-binary") mca_arg = "--llvm-mca-binary " + shell_quote(llvm_mca_path) - add_update_script_substition("%update_test_checks", extra_args=mca_arg) + add_update_script_substitution("%update_test_checks", extra_args=mca_arg) split_file_path = os.path.join(config.llvm_tools_dir, "split-file") if os.path.isfile(split_file_path): - add_update_script_substition("%update_test_body") + add_update_script_substitution("%update_test_body") llvm_mc_path = os.path.join(config.llvm_tools_dir, "llvm-mc") if os.path.isfile(llvm_mc_path): - add_update_script_substition("%update_mc_test_checks") + add_update_script_substitution("%update_mc_test_checks") diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index b108a21dbc52b..e1cc02e1a608c 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -1396,7 +1396,7 @@ def find_diff_matching(lhs: List[str], rhs: List[str]) -> List[tuple]: backlinks.append(None) # Commit to names in the matching by walking the backlinks. Recursively - # attempt to fill in more matches in-betweem. + # attempt to fill in more matches in-between. match_idx = table_candidate_idx[-1] while match_idx is not None: current = candidates[match_idx] From 72a28a3bf0b539bcdfd8f41905675ce6a890c0ac Mon Sep 17 00:00:00 2001 From: Jan Voung Date: Wed, 8 Jan 2025 08:27:16 -0500 Subject: [PATCH 014/163] [clang][dataflow] Use smart pointer caching in unchecked optional accessor (#120249) Part 2 (and final part) following https://github.com/llvm/llvm-project/pull/120102 Allows users to do things like: ``` if (o->x.has_value()) { ((*o).x).value(); } ``` where the `->` and `*` are operator overload calls. A user could instead extract the nested optional into a local variable once instead of doing two accessor calls back to back, but currently they are unsure why the code is flagged. --- .../CachedConstAccessorsLattice.h | 40 +++++++ .../Models/UncheckedOptionalAccessModel.h | 15 ++- .../SmartPointerAccessorCaching.h | 106 ++++++++++++++++++ .../Models/UncheckedOptionalAccessModel.cpp | 57 +++++++++- .../SmartPointerAccessorCaching.cpp | 21 ++++ .../CachedConstAccessorsLatticeTest.cpp | 29 +++++ .../UncheckedOptionalAccessModelTest.cpp | 48 ++++++++ 7 files changed, 302 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h index 48c5287367739..aaf89f4e94d4a 100644 --- a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h +++ b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h @@ -13,7 +13,9 @@ #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H +#include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" @@ -71,10 +73,27 @@ template class CachedConstAccessorsLattice : public Base { /// Requirements: /// /// - `CE` should return a location (GLValue or a record type). + /// + /// DEPRECATED: switch users to the below overload which takes Callee and Type + /// directly. StorageLocation *getOrCreateConstMethodReturnStorageLocation( const RecordStorageLocation &RecordLoc, const CallExpr *CE, Environment &Env, llvm::function_ref Initialize); + /// Creates or returns a previously created `StorageLocation` associated with + /// a const method call `obj.getFoo()` where `RecordLoc` is the + /// `RecordStorageLocation` of `obj`, `Callee` is the decl for `getFoo`. + /// + /// The callback `Initialize` runs on the storage location if newly created. + /// + /// Requirements: + /// + /// - `Callee` should return a location (return type is a reference type or a + /// record type). + StorageLocation &getOrCreateConstMethodReturnStorageLocation( + const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee, + Environment &Env, llvm::function_ref Initialize); + void clearConstMethodReturnValues(const RecordStorageLocation &RecordLoc) { ConstMethodReturnValues.erase(&RecordLoc); } @@ -212,6 +231,27 @@ CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( return &Loc; } +template +StorageLocation & +CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( + const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee, + Environment &Env, llvm::function_ref Initialize) { + assert(Callee != nullptr); + QualType Type = Callee->getReturnType(); + assert(!Type.isNull()); + assert(Type->isReferenceType() || Type->isRecordType()); + auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc]; + auto it = ObjMap.find(Callee); + if (it != ObjMap.end()) + return *it->second; + + StorageLocation &Loc = Env.createStorageLocation(Type.getNonReferenceType()); + Initialize(Loc); + + ObjMap.insert({Callee, &Loc}); + return Loc; +} + } // namespace dataflow } // namespace clang diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h index 713494178b97b..fb11c2e230e32 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h +++ b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h @@ -37,14 +37,13 @@ struct UncheckedOptionalAccessModelOptions { /// can't identify when their results are used safely (across calls), /// resulting in false positives in all such cases. Note: this option does not /// cover access through `operator[]`. - /// FIXME: we currently cache and equate the result of const accessors - /// returning pointers, so cover the case of operator-> followed by - /// operator->, which covers the common case of smart pointers. We also cover - /// some limited cases of returning references (if return type is an optional - /// type), so cover some cases of operator* followed by operator*. We don't - /// cover mixing operator-> and operator*. Once we are confident in this const - /// accessor caching, we shouldn't need the IgnoreSmartPointerDereference - /// option anymore. + /// + /// FIXME: we now cache and equate the result of const accessors + /// that look like unique_ptr, have both `->` (returning a pointer type) and + /// `*` (returning a reference type). This includes mixing `->` and + /// `*` in a sequence of calls as long as the object is not modified. Once we + /// are confident in this const accessor caching, we shouldn't need the + /// IgnoreSmartPointerDereference option anymore. bool IgnoreSmartPointerDereference = false; }; diff --git a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h index 3e4016518eaac..1b116a0cf76ed 100644 --- a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h +++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h @@ -27,8 +27,13 @@ #include #include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" #include "clang/AST/Stmt.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/FlowSensitive/MatchSwitch.h" +#include "clang/Analysis/FlowSensitive/StorageLocation.h" +#include "clang/Analysis/FlowSensitive/Value.h" +#include "llvm/ADT/STLFunctionalExtras.h" namespace clang::dataflow { @@ -58,6 +63,107 @@ ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow(); ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall(); ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall(); +// Common transfer functions. + +/// Returns the "canonical" callee for smart pointer operators (`*` and `->`) +/// as a key for caching. +/// +/// We choose `*` as the canonical one, since it needs a +/// StorageLocation anyway. +/// +/// Note: there may be multiple `operator*` (one const, one non-const). +/// We pick the const one, which the above provided matchers require to exist. +const FunctionDecl * +getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE); + +/// A transfer function for `operator*` (and `value`) calls that can be +/// cached. Runs the `InitializeLoc` callback to initialize any new +/// StorageLocations. +/// +/// Requirements: +/// +/// - LatticeT should use the `CachedConstAccessorsLattice` mixin. +template +void transferSmartPointerLikeCachedDeref( + const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc); + +/// A transfer function for `operator->` (and `get`) calls that can be cached. +/// Runs the `InitializeLoc` callback to initialize any new StorageLocations. +/// +/// Requirements: +/// +/// - LatticeT should use the `CachedConstAccessorsLattice` mixin. +template +void transferSmartPointerLikeCachedGet( + const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc); + +template +void transferSmartPointerLikeCachedDeref( + const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc) { + if (State.Env.getStorageLocation(*DerefExpr) != nullptr) + return; + if (SmartPointerLoc == nullptr) + return; + + const FunctionDecl *Callee = DerefExpr->getDirectCallee(); + if (Callee == nullptr) + return; + const FunctionDecl *CanonicalCallee = + getCanonicalSmartPointerLikeOperatorCallee(DerefExpr); + // This shouldn't happen, as we should at least find `Callee` itself. + assert(CanonicalCallee != nullptr); + if (CanonicalCallee != Callee) { + // When using the provided matchers, we should always get a reference to + // the same type. + assert(CanonicalCallee->getReturnType()->isReferenceType() && + Callee->getReturnType()->isReferenceType()); + assert(CanonicalCallee->getReturnType() + .getNonReferenceType() + ->getCanonicalTypeUnqualified() == + Callee->getReturnType() + .getNonReferenceType() + ->getCanonicalTypeUnqualified()); + } + + StorageLocation &LocForValue = + State.Lattice.getOrCreateConstMethodReturnStorageLocation( + *SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc); + State.Env.setStorageLocation(*DerefExpr, LocForValue); +} + +template +void transferSmartPointerLikeCachedGet( + const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc) { + if (SmartPointerLoc == nullptr) + return; + + const FunctionDecl *CanonicalCallee = + getCanonicalSmartPointerLikeOperatorCallee(GetExpr); + + if (CanonicalCallee != nullptr) { + auto &LocForValue = + State.Lattice.getOrCreateConstMethodReturnStorageLocation( + *SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc); + State.Env.setValue(*GetExpr, + State.Env.template create(LocForValue)); + } else { + // Otherwise, just cache the pointer value as if it was a const accessor. + Value *Val = State.Lattice.getOrCreateConstMethodReturnValue( + *SmartPointerLoc, GetExpr, State.Env); + if (Val == nullptr) + return; + State.Env.setValue(*GetExpr, *Val); + } +} + } // namespace clang::dataflow #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index da5dda063344f..e1394e28cd49a 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -25,8 +25,10 @@ #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/Formula.h" #include "clang/Analysis/FlowSensitive/RecordOps.h" +#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" @@ -555,24 +557,25 @@ void handleConstMemberCall(const CallExpr *CE, LatticeTransferState &State) { // If the const method returns an optional or reference to an optional. if (RecordLoc != nullptr && isSupportedOptionalType(CE->getType())) { - StorageLocation *Loc = + const FunctionDecl *DirectCallee = CE->getDirectCallee(); + if (DirectCallee == nullptr) + return; + StorageLocation &Loc = State.Lattice.getOrCreateConstMethodReturnStorageLocation( - *RecordLoc, CE, State.Env, [&](StorageLocation &Loc) { + *RecordLoc, DirectCallee, State.Env, [&](StorageLocation &Loc) { setHasValue(cast(Loc), State.Env.makeAtomicBoolValue(), State.Env); }); - if (Loc == nullptr) - return; if (CE->isGLValue()) { // If the call to the const method returns a reference to an optional, // link the call expression to the cached StorageLocation. - State.Env.setStorageLocation(*CE, *Loc); + State.Env.setStorageLocation(*CE, Loc); } else { // If the call to the const method returns an optional by value, we // need to use CopyRecord to link the optional to the result object // of the call expression. auto &ResultLoc = State.Env.getResultObjectLocation(*CE); - copyRecord(*cast(Loc), ResultLoc, State.Env); + copyRecord(cast(Loc), ResultLoc, State.Env); } return; } @@ -1031,6 +1034,48 @@ auto buildTransferMatchSwitch() { transferOptionalAndValueCmp(Cmp, Cmp->getArg(1), State.Env); }) + // Smart-pointer-like operator* and operator-> calls that may look like + // const accessors (below) but need special handling to allow mixing + // the accessor calls. + .CaseOfCFGStmt( + isSmartPointerLikeOperatorStar(), + [](const CXXOperatorCallExpr *E, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + transferSmartPointerLikeCachedDeref( + E, + dyn_cast_or_null( + getLocBehindPossiblePointer(*E->getArg(0), State.Env)), + State, [](StorageLocation &Loc) {}); + }) + .CaseOfCFGStmt( + isSmartPointerLikeOperatorArrow(), + [](const CXXOperatorCallExpr *E, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + transferSmartPointerLikeCachedGet( + E, + dyn_cast_or_null( + getLocBehindPossiblePointer(*E->getArg(0), State.Env)), + State, [](StorageLocation &Loc) {}); + }) + .CaseOfCFGStmt( + isSmartPointerLikeValueMethodCall(), + [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + transferSmartPointerLikeCachedDeref( + E, getImplicitObjectLocation(*E, State.Env), State, + [](StorageLocation &Loc) {}); + }) + .CaseOfCFGStmt( + isSmartPointerLikeGetMethodCall(), + [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + transferSmartPointerLikeCachedGet( + E, getImplicitObjectLocation(*E, State.Env), State, + [](StorageLocation &Loc) {}); + }) + // const accessor calls .CaseOfCFGStmt(isZeroParamConstMemberCall(), transferValue_ConstMemberCall) diff --git a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp index a0c81aa933da8..c58bd309545db 100644 --- a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp +++ b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp @@ -132,6 +132,7 @@ ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow() { callee(cxxMethodDecl(parameterCountIs(0), returns(pointerType()), ofClass(smartPointerClassWithGetOrValue())))); } + ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall() { return cxxMemberCallExpr(callee( cxxMethodDecl(parameterCountIs(0), returns(referenceType()), @@ -144,4 +145,24 @@ ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall() { ofClass(smartPointerClassWithGet())))); } +const FunctionDecl * +getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE) { + const FunctionDecl *CanonicalCallee = nullptr; + const CXXMethodDecl *Callee = + cast_or_null(CE->getDirectCallee()); + if (Callee == nullptr) + return nullptr; + const CXXRecordDecl *RD = Callee->getParent(); + if (RD == nullptr) + return nullptr; + for (const auto *MD : RD->methods()) { + if (MD->getOverloadedOperator() == OO_Star && MD->isConst() && + MD->getNumParams() == 0 && MD->getReturnType()->isReferenceType()) { + CanonicalCallee = MD; + break; + } + } + return CanonicalCallee; +} + } // namespace clang::dataflow diff --git a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp index 6488833bd14cf..d27f6a6d27e71 100644 --- a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp @@ -148,6 +148,35 @@ TEST_F(CachedConstAccessorsLatticeTest, SameLocBeforeClearOrDiffAfterClear) { EXPECT_NE(Loc3, Loc2); } +TEST_F(CachedConstAccessorsLatticeTest, + SameLocBeforeClearOrDiffAfterClearWithCallee) { + CommonTestInputs Inputs; + auto *CE = Inputs.CallRef; + RecordStorageLocation Loc(Inputs.SType, RecordStorageLocation::FieldToLoc(), + {}); + + LatticeT Lattice; + auto NopInit = [](StorageLocation &) {}; + const FunctionDecl *Callee = CE->getDirectCallee(); + ASSERT_NE(Callee, nullptr); + StorageLocation &Loc1 = Lattice.getOrCreateConstMethodReturnStorageLocation( + Loc, Callee, Env, NopInit); + auto NotCalled = [](StorageLocation &) { + ASSERT_TRUE(false) << "Not reached"; + }; + StorageLocation &Loc2 = Lattice.getOrCreateConstMethodReturnStorageLocation( + Loc, Callee, Env, NotCalled); + + EXPECT_EQ(&Loc1, &Loc2); + + Lattice.clearConstMethodReturnStorageLocations(Loc); + StorageLocation &Loc3 = Lattice.getOrCreateConstMethodReturnStorageLocation( + Loc, Callee, Env, NopInit); + + EXPECT_NE(&Loc3, &Loc1); + EXPECT_NE(&Loc3, &Loc2); +} + TEST_F(CachedConstAccessorsLatticeTest, SameStructValBeforeClearOrDiffAfterClear) { TestAST AST(R"cpp( diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index de16f6be8eedb..19c3ff49eab27 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -3771,6 +3771,54 @@ TEST_P(UncheckedOptionalAccessTest, ConstPointerAccessorWithModInBetween) { /*IgnoreSmartPointerDereference=*/false); } +TEST_P(UncheckedOptionalAccessTest, SmartPointerAccessorMixed) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + $ns::$optional x; + }; + + namespace absl { + template + class StatusOr { + public: + bool ok() const; + + const T& operator*() const&; + T& operator*() &; + + const T* operator->() const; + T* operator->(); + + const T& value() const; + T& value(); + }; + } + + void target(absl::StatusOr &mut, const absl::StatusOr &imm) { + if (!mut.ok() || !imm.ok()) + return; + + if (mut->x.has_value()) { + mut->x.value(); + ((*mut).x).value(); + (mut.value().x).value(); + + // check flagged after modifying + mut = imm; + mut->x.value(); // [[unsafe]] + } + if (imm->x.has_value()) { + imm->x.value(); + ((*imm).x).value(); + (imm.value().x).value(); + } + } + )cc", + /*IgnoreSmartPointerDereference=*/false); +} + TEST_P(UncheckedOptionalAccessTest, ConstBoolAccessor) { ExpectDiagnosticsFor(R"cc( #include "unchecked_optional_access_test.h" From 81fc3add1e627c23b7270fe2739cdacc09063e54 Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Wed, 8 Jan 2025 14:45:19 +0100 Subject: [PATCH 015/163] [clang] Avoid re-evaluating field bitwidth (#117732) Save the bitwidth value as a `ConstantExpr` with the value set. Remove the `ASTContext` parameter from `getBitWidthValue()`, so the latter simply returns the value from the `ConstantExpr` instead of constant-evaluating the bitwidth expression every time it is called. --- .../bugprone/NarrowingConversionsCheck.cpp | 2 +- .../bugprone/TooSmallLoopVariableCheck.cpp | 2 +- .../hicpp/MultiwayPathsCoveredCheck.cpp | 2 +- clang-tools-extra/clangd/Hover.cpp | 2 +- clang/include/clang/AST/Decl.h | 6 ++++-- clang/include/clang/ASTMatchers/ASTMatchers.h | 3 +-- clang/lib/AST/ASTContext.cpp | 10 ++++----- clang/lib/AST/ByteCode/Interp.h | 10 ++++----- .../lib/AST/ByteCode/InterpBuiltinBitCast.cpp | 8 +++---- clang/lib/AST/Decl.cpp | 16 +++++++++----- clang/lib/AST/DeclCXX.cpp | 2 +- clang/lib/AST/Expr.cpp | 3 +-- clang/lib/AST/ExprConstant.cpp | 2 +- clang/lib/AST/Randstruct.cpp | 2 +- clang/lib/AST/RecordLayoutBuilder.cpp | 6 +++--- clang/lib/CodeGen/ABIInfo.cpp | 2 +- clang/lib/CodeGen/ABIInfoImpl.cpp | 2 +- clang/lib/CodeGen/CGCall.cpp | 6 +++--- clang/lib/CodeGen/CGClass.cpp | 2 +- clang/lib/CodeGen/CGDebugInfo.cpp | 8 +++---- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 6 +++--- clang/lib/CodeGen/CGObjCMac.cpp | 3 +-- clang/lib/CodeGen/CGObjCRuntime.cpp | 2 +- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 20 +++++++++--------- clang/lib/CodeGen/SwiftCallingConv.cpp | 2 +- clang/lib/CodeGen/Targets/LoongArch.cpp | 2 +- clang/lib/CodeGen/Targets/RISCV.cpp | 2 +- clang/lib/CodeGen/Targets/X86.cpp | 2 +- clang/lib/CodeGen/Targets/XCore.cpp | 2 +- .../Frontend/Rewrite/RewriteModernObjC.cpp | 3 ++- clang/lib/Sema/SemaChecking.cpp | 10 ++++----- clang/lib/Sema/SemaDecl.cpp | 21 ++++++++++--------- clang/lib/Sema/SemaDeclCXX.cpp | 6 +++--- clang/lib/Sema/SemaDeclObjC.cpp | 3 +-- clang/lib/Sema/SemaOverload.cpp | 2 +- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 2 +- clang/tools/libclang/CXType.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 4 ++-- 38 files changed, 96 insertions(+), 94 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp index a950704208c73..408390ebc70b6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp @@ -38,7 +38,7 @@ AST_MATCHER(FieldDecl, hasIntBitwidth) { assert(Node.isBitField()); const ASTContext &Ctx = Node.getASTContext(); unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy); - unsigned CurrentBitWidth = Node.getBitWidthValue(Ctx); + unsigned CurrentBitWidth = Node.getBitWidthValue(); return IntBitWidth == CurrentBitWidth; } diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp index a73d46f01d9b2..4ceeefb78ee82 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -124,7 +124,7 @@ static MagnitudeBits calcMagnitudeBits(const ASTContext &Context, unsigned SignedBits = IntExprType->isUnsignedIntegerType() ? 0U : 1U; if (const auto *BitField = IntExpr->getSourceBitField()) { - unsigned BitFieldWidth = BitField->getBitWidthValue(Context); + unsigned BitFieldWidth = BitField->getBitWidthValue(); return {BitFieldWidth - SignedBits, BitFieldWidth}; } diff --git a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp index 47dafca2d03ff..7028c3958f103 100644 --- a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp @@ -160,7 +160,7 @@ void MultiwayPathsCoveredCheck::handleSwitchWithoutDefault( } if (const auto *BitfieldDecl = Result.Nodes.getNodeAs("bitfield")) { - return twoPow(BitfieldDecl->getBitWidthValue(*Result.Context)); + return twoPow(BitfieldDecl->getBitWidthValue()); } return static_cast(0); diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 298fa79e3fd0b..5e136d0e76ece 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -1018,7 +1018,7 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Record); HI.Offset = Layout.getFieldOffset(FD->getFieldIndex()); if (FD->isBitField()) - HI.Size = FD->getBitWidthValue(Ctx); + HI.Size = FD->getBitWidthValue(); else if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FD->getType())) HI.Size = FD->isZeroSize(Ctx) ? 0 : Size->getQuantity() * 8; if (HI.Size) { diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 67ee0bb412692..5670072ab4a76 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3142,7 +3142,9 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { /// Computes the bit width of this field, if this is a bit field. /// May not be called on non-bitfields. - unsigned getBitWidthValue(const ASTContext &Ctx) const; + /// Note that in order to successfully use this function, the bitwidth + /// expression must be a ConstantExpr with a valid integer result set. + unsigned getBitWidthValue() const; /// Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). @@ -3173,7 +3175,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { /// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields /// at all and instead act as a separator between contiguous runs of other /// bit-fields. - bool isZeroLengthBitField(const ASTContext &Ctx) const; + bool isZeroLengthBitField() const; /// Determine if this field is a subobject of zero size, that is, either a /// zero-length bit-field or a field of empty class type with the diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index f10135d7a901f..ef3d34d4123d8 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -708,8 +708,7 @@ AST_MATCHER(FieldDecl, isBitField) { /// fieldDecl(hasBitWidth(2)) /// matches 'int a;' and 'int c;' but not 'int b;'. AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { - return Node.isBitField() && - Node.getBitWidthValue(Finder->getASTContext()) == Width; + return Node.isBitField() && Node.getBitWidthValue() == Width; } /// Matches non-static data members that have an in-class initializer. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b10513f49a8d1..46431634d9102 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2795,7 +2795,7 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context, if (Field->isUnnamedBitField()) return 0; - int64_t BitfieldSize = Field->getBitWidthValue(Context); + int64_t BitfieldSize = Field->getBitWidthValue(); if (IsBitIntType) { if ((unsigned)BitfieldSize > cast(Field->getType())->getNumBits()) @@ -7769,7 +7769,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { QualType FT = Field->getType(); - uint64_t BitWidth = Field->getBitWidthValue(*this); + uint64_t BitWidth = Field->getBitWidthValue(); uint64_t IntSize = getTypeSize(IntTy); // C++ [conv.prom]p5: // A prvalue for an integral bit-field can be converted to a prvalue of type @@ -8797,7 +8797,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += getObjCEncodingForPrimitiveType(Ctx, BT); } } - S += llvm::utostr(FD->getBitWidthValue(*Ctx)); + S += llvm::utostr(FD->getBitWidthValue()); } // Helper function for determining whether the encoded type string would include @@ -9223,7 +9223,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } for (FieldDecl *Field : RDecl->fields()) { - if (!Field->isZeroLengthBitField(*this) && Field->isZeroSize(*this)) + if (!Field->isZeroLengthBitField() && Field->isZeroSize(*this)) continue; uint64_t offs = layout.getFieldOffset(Field->getFieldIndex()); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), @@ -9320,7 +9320,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); #ifndef NDEBUG - CurOffs += field->getBitWidthValue(*this); + CurOffs += field->getBitWidthValue(); #endif } else { QualType qt = field->getType(); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index d2aec69072e04..93a91976a31bf 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1471,8 +1471,7 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, return false; const Pointer &Field = This.atField(FieldOffset); const auto &Value = S.Stk.pop(); - Field.deref() = - Value.truncate(F->Decl->getBitWidthValue(S.getASTContext())); + Field.deref() = Value.truncate(F->Decl->getBitWidthValue()); Field.initialize(); return true; } @@ -1495,8 +1494,7 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) { assert(F->isBitField()); const T &Value = S.Stk.pop(); const Pointer &Field = S.Stk.peek().atField(F->Offset); - Field.deref() = - Value.truncate(F->Decl->getBitWidthValue(S.getASTContext())); + Field.deref() = Value.truncate(F->Decl->getBitWidthValue()); Field.activate(); Field.initialize(); return true; @@ -1750,7 +1748,7 @@ bool StoreBitField(InterpState &S, CodePtr OpPC) { if (Ptr.canBeInitialized()) Ptr.initialize(); if (const auto *FD = Ptr.getField()) - Ptr.deref() = Value.truncate(FD->getBitWidthValue(S.getASTContext())); + Ptr.deref() = Value.truncate(FD->getBitWidthValue()); else Ptr.deref() = Value; return true; @@ -1765,7 +1763,7 @@ bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) { if (Ptr.canBeInitialized()) Ptr.initialize(); if (const auto *FD = Ptr.getField()) - Ptr.deref() = Value.truncate(FD->getBitWidthValue(S.getASTContext())); + Ptr.deref() = Value.truncate(FD->getBitWidthValue()); else Ptr.deref() = Value; return true; diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index 57c1fab5d6ab4..f4c54551a9a60 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -269,7 +269,7 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx, Bits BitWidth = FullBitWidth; if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), + BitWidth = Bits(std::min(FD->getBitWidthValue(), (unsigned)FullBitWidth.getQuantity())); else if (T == PT_Bool && PackedBools) BitWidth = Bits(1); @@ -301,8 +301,8 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx, assert(NumBits.isFullByte()); assert(NumBits.getQuantity() <= FullBitWidth.getQuantity()); F.bitcastToMemory(Buff.get()); - // Now, only (maybe) swap the actual size of the float, excluding the - // padding bits. + // Now, only (maybe) swap the actual size of the float, excluding + // the padding bits. if (llvm::sys::IsBigEndianHost) swapBytes(Buff.get(), NumBits.roundToBytes()); @@ -406,7 +406,7 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, Bits BitWidth; if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), + BitWidth = Bits(std::min(FD->getBitWidthValue(), (unsigned)FullBitWidth.getQuantity())); else if (T == PT_Bool && PackedBools) BitWidth = Bits(1); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 741e908cf9bc5..37baf06cc55dd 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4599,18 +4599,24 @@ void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) { Init = NewInit; } -unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { +unsigned FieldDecl::getBitWidthValue() const { assert(isBitField() && "not a bitfield"); - return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); + assert(isa(getBitWidth())); + assert(cast(getBitWidth())->hasAPValueResult()); + assert(cast(getBitWidth())->getAPValueResult().isInt()); + return cast(getBitWidth()) + ->getAPValueResult() + .getInt() + .getZExtValue(); } -bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const { +bool FieldDecl::isZeroLengthBitField() const { return isUnnamedBitField() && !getBitWidth()->isValueDependent() && - getBitWidthValue(Ctx) == 0; + getBitWidthValue() == 0; } bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { - if (isZeroLengthBitField(Ctx)) + if (isZeroLengthBitField()) return true; // C++2a [intro.object]p7: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index af73c658d6a0c..21e128f4a4a7d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -993,7 +993,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++ [meta.unary.prop]p4: [LWG2358] // T is a class type [...] with [...] no unnamed bit-fields of non-zero // length - if (data().Empty && !Field->isZeroLengthBitField(Context) && + if (data().Empty && !Field->isZeroLengthBitField() && Context.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6) data().Empty = false; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index ba66d36278567..5331357b5d1fe 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -196,8 +196,7 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { if (const FieldDecl *FD = E->getSourceBitField()) if (!Semantic && FD->getType()->isUnsignedIntegerType() && - !FD->getBitWidth()->isValueDependent() && - FD->getBitWidthValue(FD->getASTContext()) == 1) + !FD->getBitWidth()->isValueDependent() && FD->getBitWidthValue() == 1) return true; return false; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e220f69b3a4f5..716602a5d7c50 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2875,7 +2875,7 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, APSInt &Int = Value.getInt(); unsigned OldBitWidth = Int.getBitWidth(); - unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); + unsigned NewBitWidth = FD->getBitWidthValue(); if (NewBitWidth < OldBitWidth) Int = Int.trunc(NewBitWidth).extend(OldBitWidth); return true; diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp index b484afa4997bb..4537ba5309e0b 100644 --- a/clang/lib/AST/Randstruct.cpp +++ b/clang/lib/AST/Randstruct.cpp @@ -91,7 +91,7 @@ void randomizeStructureLayoutImpl(const ASTContext &Context, auto FieldIter = FieldsOut.begin(); FieldDecl *FD = *FieldIter; - if (FD->isBitField() && !FD->isZeroLengthBitField(Context)) { + if (FD->isBitField() && !FD->isZeroLengthBitField()) { // Start a bitfield run if this is the first bitfield we have found. if (!CurrentBitfieldRun) CurrentBitfieldRun = std::make_unique(); diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f749d3a705fc9..e6af27e8c9677 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1542,7 +1542,7 @@ static bool isAIXLayout(const ASTContext &Context) { void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr(); - uint64_t FieldSize = D->getBitWidthValue(Context); + uint64_t FieldSize = D->getBitWidthValue(); TypeInfo FieldInfo = Context.getTypeInfo(D->getType()); uint64_t StorageUnitSize = FieldInfo.Width; unsigned FieldAlign = FieldInfo.Align; @@ -3022,7 +3022,7 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { } void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { - unsigned Width = FD->getBitWidthValue(Context); + unsigned Width = FD->getBitWidthValue(); if (Width == 0) { layoutZeroWidthBitField(FD); return; @@ -3692,7 +3692,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, if (Field.isBitField()) { uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset); unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits; - unsigned Width = Field.getBitWidthValue(C); + unsigned Width = Field.getBitWidthValue(); PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel); } else { PrintOffset(OS, FieldOffset, IndentLevel); diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index 8e76cf15b642c..642bca9e8b76d 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -106,7 +106,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, continue; if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() && - FD->isZeroLengthBitField(getContext())) + FD->isZeroLengthBitField()) continue; uint64_t FldMembers; diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 79300df15d0e2..795874059bda7 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -303,7 +303,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD) { - if (FD->isZeroLengthBitField(Context)) + if (FD->isZeroLengthBitField()) return true; if (FD->isUnnamedBitField()) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7b0ef4be98619..d497fcff37f87 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -954,7 +954,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { CharUnits UnionSize = CharUnits::Zero(); for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField(Context)) + if (FD->isZeroLengthBitField()) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -974,7 +974,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { } for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField(Context)) + if (FD->isZeroLengthBitField()) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -3682,7 +3682,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) { const FieldDecl *F = *I; - if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) || + if (F->isUnnamedBitField() || F->isZeroLengthBitField() || F->getType()->isIncompleteArrayType()) continue; diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index c45688bd1ed3c..8c190732c8cdc 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -945,7 +945,7 @@ namespace { ASTContext &Ctx = CGF.getContext(); unsigned LastFieldSize = LastField->isBitField() - ? LastField->getBitWidthValue(Ctx) + ? LastField->getBitWidthValue() : Ctx.toBits( Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width); uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize - diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 560d4ce293365..d7e5e95b7873a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1721,8 +1721,7 @@ llvm::DIDerivedType *CGDebugInfo::createBitFieldSeparatorIfNeeded( assert(PreviousBitfield->isBitField()); - ASTContext &Context = CGM.getContext(); - if (!PreviousBitfield->isZeroLengthBitField(Context)) + if (!PreviousBitfield->isZeroLengthBitField()) return nullptr; QualType Ty = PreviousBitfield->getType(); @@ -3214,9 +3213,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. - FieldSize = Field->isBitField() - ? Field->getBitWidthValue(CGM.getContext()) - : CGM.getContext().getTypeSize(FType); + FieldSize = Field->isBitField() ? Field->getBitWidthValue() + : CGM.getContext().getTypeSize(FType); FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); } diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 6a02e4dbf84d1..d90c44d770d14 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -25,7 +25,7 @@ using namespace CodeGen; static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, ASTContext &Ctx) { if (FD && FD->isBitField()) - return FD->getBitWidthValue(Ctx); + return FD->getBitWidthValue(); return Ctx.getTypeSize(FT); } @@ -255,7 +255,7 @@ struct GenBinaryFuncName : CopyStructVisitor, IsMove>, void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset) { // Zero-length bit-fields don't need to be copied/assigned. - if (FD && FD->isZeroLengthBitField(this->Ctx)) + if (FD && FD->isZeroLengthBitField()) return; // Because volatile fields can be bit-fields and are individually copied, @@ -544,7 +544,7 @@ struct GenBinaryFunc : CopyStructVisitor, LValue DstLV, SrcLV; if (FD) { // No need to copy zero-length bit-fields. - if (FD->isZeroLengthBitField(this->CGF->getContext())) + if (FD->isZeroLengthBitField()) return; QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 7b85dcc2c7984..dd900f9b32fb7 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2543,8 +2543,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (LastFieldBitfieldOrUnnamed) { if (LastFieldBitfieldOrUnnamed->isBitField()) { // Last field was a bitfield. Must update the info. - uint64_t BitFieldSize - = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); + uint64_t BitFieldSize = LastFieldBitfieldOrUnnamed->getBitWidthValue(); unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + ((BitFieldSize % ByteSizeInBits) != 0); CharUnits Size = CharUnits::fromQuantity(UnsSize); diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 01d0f35da1964..b438a92a4fd62 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -89,7 +89,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); - uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); + uint64_t BitFieldSize = Ivar->getBitWidthValue(); CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits)); CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index ea44e6f21f3c8..4afcd9d6d32cc 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -148,8 +148,8 @@ struct CGRecordLowering { llvm::Type *Type = Types.ConvertTypeForMem(FD->getType()); if (!FD->isBitField()) return Type; if (isDiscreteBitFieldABI()) return Type; - return getIntNType(std::min(FD->getBitWidthValue(Context), - (unsigned)Context.toBits(getSize(Type)))); + return getIntNType(std::min(FD->getBitWidthValue(), + (unsigned)Context.toBits(getSize(Type)))); } /// Gets the llvm Basesubobject type from a CXXRecordDecl. llvm::Type *getStorageType(const CXXRecordDecl *RD) const { @@ -242,7 +242,7 @@ void CGRecordLowering::setBitFieldInfo( CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()]; Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType(); Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset)); - Info.Size = FD->getBitWidthValue(Context); + Info.Size = FD->getBitWidthValue(); Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType); Info.StorageOffset = StartOffset; if (Info.Size > Info.StorageSize) @@ -322,7 +322,7 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { // been doing and cause lit tests to change. for (const auto *Field : D->fields()) { if (Field->isBitField()) { - if (Field->isZeroLengthBitField(Context)) + if (Field->isZeroLengthBitField()) continue; llvm::Type *FieldType = getStorageType(Field); if (LayoutSize < getSize(FieldType)) @@ -423,7 +423,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, uint64_t StartBitOffset, Tail = 0; for (; Field != FieldEnd && Field->isBitField(); ++Field) { // Zero-width bitfields end runs. - if (Field->isZeroLengthBitField(Context)) { + if (Field->isZeroLengthBitField()) { Run = FieldEnd; continue; } @@ -559,7 +559,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // Bitfield potentially begins a new span. This includes zero-length // bitfields on non-aligning targets that lie at character boundaries // (those are barriers to merging). - if (Field->isZeroLengthBitField(Context)) + if (Field->isZeroLengthBitField()) Barrier = true; AtAlignedBoundary = true; } @@ -697,7 +697,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, } Members.push_back(StorageInfo(BeginOffset, Type)); for (; Begin != BestEnd; ++Begin) - if (!Begin->isZeroLengthBitField(Context)) + if (!Begin->isZeroLengthBitField()) Members.push_back( MemberInfo(BeginOffset, MemberInfo::Field, nullptr, *Begin)); } @@ -709,7 +709,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, "Accumulating past end of bitfields"); assert(!Barrier && "Accumulating across barrier"); // Accumulate this bitfield into the current (potential) span. - BitSizeSinceBegin += Field->getBitWidthValue(Context); + BitSizeSinceBegin += Field->getBitWidthValue(); ++Field; } } @@ -813,7 +813,7 @@ void CGRecordLowering::computeVolatileBitfields() { bool Conflict = false; for (const auto *F : D->fields()) { // Allow sized bit-fields overlaps. - if (F->isBitField() && !F->isZeroLengthBitField(Context)) + if (F->isBitField() && !F->isZeroLengthBitField()) continue; const CharUnits FOffset = Context.toCharUnitsFromBits( @@ -823,7 +823,7 @@ void CGRecordLowering::computeVolatileBitfields() { // fields after and before it should be race condition free. // The AAPCS acknowledges it and imposes no restritions when the // natural container overlaps a zero-length bit-field. - if (F->isZeroLengthBitField(Context)) { + if (F->isZeroLengthBitField()) { if (End > FOffset && StorageOffset < FOffset) { Conflict = true; break; diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 0873896df213e..1ff4ece2811ec 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -186,7 +186,7 @@ void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield, uint64_t bitfieldBitBegin) { assert(bitfield->isBitField()); auto &ctx = CGM.getContext(); - auto width = bitfield->getBitWidthValue(ctx); + auto width = bitfield->getBitWidthValue(); // We can ignore zero-width bit-fields. if (width == 0) return; diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 6af9375461f09..6c90e48a5ea41 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -192,7 +192,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( for (const FieldDecl *FD : RD->fields()) { QualType QTy = FD->getType(); if (FD->isBitField()) { - unsigned BitWidth = FD->getBitWidthValue(getContext()); + unsigned BitWidth = FD->getBitWidthValue(); // Zero-width bitfields are ignored. if (BitWidth == 0) continue; diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 873e696e1328f..2b70f2bd3f38b 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -246,7 +246,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex()); QualType QTy = FD->getType(); if (FD->isBitField()) { - unsigned BitWidth = FD->getBitWidthValue(getContext()); + unsigned BitWidth = FD->getBitWidthValue(); // Allow a bitfield with a type greater than XLen as long as the // bitwidth is XLen or less. if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 7f73bf2a65266..5ee5179dd0f3e 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2130,7 +2130,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, if (BitField) { assert(!i->isUnnamedBitField()); uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - uint64_t Size = i->getBitWidthValue(getContext()); + uint64_t Size = i->getBitWidthValue(); uint64_t EB_Lo = Offset / 64; uint64_t EB_Hi = (Offset + Size - 1) / 64; diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index f3e241171b872..ced4981fd124f 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -343,7 +343,7 @@ static bool extractFieldType(SmallVectorImpl &FE, if (Field->isBitField()) { Enc += "b("; llvm::raw_svector_ostream OS(Enc); - OS << Field->getBitWidthValue(CGM.getContext()); + OS << Field->getBitWidthValue(); Enc += ':'; } if (!appendType(Enc, Field->getType(), CGM, TSC)) diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 8cdb463e2c99f..fc65559e9d4a5 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -3699,7 +3699,8 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Type.getAsStringInternal(Name, Context->getPrintingPolicy()); Result += Name; if (fieldDecl->isBitField()) { - Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); + Result += " : "; + Result += utostr(fieldDecl->getBitWidthValue()); } else if (EleboratedType && Type->isArrayType()) { const ArrayType *AT = Context->getAsArrayType(Type); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 28dcfaac2e84f..881907ac311a3 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -658,7 +658,7 @@ struct BuiltinDumpStructGenerator { Format += ": %zu "; QualType SizeT = S.Context.getSizeType(); llvm::APInt BitWidth(S.Context.getIntWidth(SizeT), - FD->getBitWidthValue(S.Context)); + FD->getBitWidthValue()); Args.push_back(IntegerLiteral::Create(S.Context, BitWidth, SizeT, Loc)); } @@ -10027,7 +10027,7 @@ static std::optional TryGetExprRange(ASTContext &C, const Expr *E, Approximate); if (const auto *BitField = E->getSourceBitField()) - return IntRange(BitField->getBitWidthValue(C), + return IntRange(BitField->getBitWidthValue(), BitField->getType()->isUnsignedIntegerOrEnumerationType()); if (GetExprType(E)->isVoidType()) @@ -10580,7 +10580,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, return false; Expr *OriginalInit = Init->IgnoreParenImpCasts(); - unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); + unsigned FieldWidth = Bitfield->getBitWidthValue(); Expr::EvalResult Result; if (!OriginalInit->EvaluateAsInt(Result, S.Context, @@ -14044,8 +14044,8 @@ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1, if (Field1->isBitField()) { // Make sure that the bit-fields are the same length. - unsigned Bits1 = Field1->getBitWidthValue(C); - unsigned Bits2 = Field2->getBitWidthValue(C); + unsigned Bits1 = Field1->getBitWidthValue(); + unsigned Bits2 = Field2->getBitWidthValue(); if (Bits1 != Bits2) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4001c4d263f1d..9f9510a6ab275 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18376,7 +18376,9 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, } } - return BitWidth; + if (isa(BitWidth)) + return BitWidth; + return ConstantExpr::Create(getASTContext(), BitWidth, APValue{Value}); } Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, @@ -18751,7 +18753,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast(ivarDecl); - if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context)) + if (!Ivar->isBitField() || Ivar->isZeroLengthBitField()) return; ObjCInterfaceDecl *ID = dyn_cast(CurContext); if (!ID) { @@ -18766,14 +18768,13 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, // All conditions are met. Add a new bitfield to the tail end of ivars. llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); + Expr *BitWidth = + ConstantExpr::Create(Context, BW, APValue(llvm::APSInt(Zero))); - Ivar = ObjCIvarDecl::Create(Context, cast(CurContext), - DeclLoc, DeclLoc, nullptr, - Context.CharTy, - Context.getTrivialTypeSourceInfo(Context.CharTy, - DeclLoc), - ObjCIvarDecl::Private, BW, - true); + Ivar = ObjCIvarDecl::Create( + Context, cast(CurContext), DeclLoc, DeclLoc, nullptr, + Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy, DeclLoc), + ObjCIvarDecl::Private, BitWidth, true); AllIvarDecls.push_back(Ivar); } @@ -19403,7 +19404,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; if (I->isUnnamedBitField()) { - if (!I->isZeroLengthBitField(Context)) + if (!I->isZeroLengthBitField()) ZeroSize = false; } else { ++NonBitFields; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c5a72cf812ebc..c4bee44f5ec04 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4877,7 +4877,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (Field->isZeroLengthBitField(SemaRef.Context)) + if (Field->isZeroLengthBitField()) return false; Expr *MemberExprBase = @@ -15041,7 +15041,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isZeroLengthBitField(Context)) + if (Field->isZeroLengthBitField()) continue; QualType FieldType = Field->getType().getNonReferenceType(); @@ -15428,7 +15428,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isZeroLengthBitField(Context)) + if (Field->isZeroLengthBitField()) continue; QualType FieldType = Field->getType().getNonReferenceType(); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 6e6174ba17c55..f97f17e8c9658 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2210,8 +2210,7 @@ void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, << ImplIvar->getType() << ClsIvar->getType(); Diag(ClsIvar->getLocation(), diag::note_previous_definition); } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && - ImplIvar->getBitWidthValue(Context) != - ClsIvar->getBitWidthValue(Context)) { + ImplIvar->getBitWidthValue() != ClsIvar->getBitWidthValue()) { Diag(ImplIvar->getBitWidth()->getBeginLoc(), diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7589701fb81de..75a6d2b6a1dbb 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -516,7 +516,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (const FieldDecl *BitField = Initializer->getSourceBitField()) { if (BitField->getBitWidth()->isValueDependent()) DependentBitField = true; - else if (unsigned BitFieldWidth = BitField->getBitWidthValue(Ctx); + else if (unsigned BitFieldWidth = BitField->getBitWidthValue(); BitFieldWidth < FromWidth) { if (CanRepresentAll(FromSigned, BitFieldWidth, ToSigned, ToWidth)) return NK_Not_Narrowing; diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index ad45ab5757a5a..6266878565c52 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -931,7 +931,7 @@ collectSubRegionBindings(SmallVectorImpl &Bindings, Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth(); } else if (const FieldRegion *FR = dyn_cast(Top)) { if (FR->getDecl()->isBitField()) - Length = FR->getDecl()->getBitWidthValue(SVB.getContext()); + Length = FR->getDecl()->getBitWidthValue(); } for (const auto &StoreEntry : Cluster) { diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index b4df12405cf35..990daadd322dc 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -381,7 +381,7 @@ int clang_getFieldDeclBitWidth(CXCursor C) { if (const FieldDecl *FD = dyn_cast_or_null(D)) { if (FD->isBitField() && !FD->getBitWidth()->isValueDependent()) - return FD->getBitWidthValue(getCursorContext(C)); + return FD->getBitWidthValue(); } } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index d197d30df3adf..ef76ee80d7c7b 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -3392,12 +3392,12 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) { FirstDeclMatcher().match(FromTU, fieldDecl(hasName("x"))); ASSERT_TRUE(FromF->isBitField()); - ASSERT_EQ(3u, FromF->getBitWidthValue(FromTU->getASTContext())); + ASSERT_EQ(3u, FromF->getBitWidthValue()); auto *ToField = Import(FromF, Lang_CXX03); auto *ToTU = ToField->getTranslationUnitDecl(); EXPECT_TRUE(ToField->isBitField()); - EXPECT_EQ(3u, ToField->getBitWidthValue(ToTU->getASTContext())); + EXPECT_EQ(3u, ToField->getBitWidthValue()); const auto *FromBT = FromF->getBitWidth()->getType()->getAs(); const auto *ToBT = ToField->getBitWidth()->getType()->getAs(); From 35c5e56b6113b468b521c071ac141b4bb94da1d7 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 8 Jan 2025 14:43:09 +0100 Subject: [PATCH 016/163] Clean up -Wdangling-assignment-gsl in clang and mlir These are triggering after b037bceef6a40c5c00c1f67cc5a334e2c4e5e041. --- clang-tools-extra/include-cleaner/lib/Analysis.cpp | 3 ++- clang/tools/driver/driver.cpp | 8 +++++--- mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp | 3 ++- mlir/lib/Dialect/SCF/Utils/Utils.cpp | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp index 16013f53894e8..e3a4834cb19ae 100644 --- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp +++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp @@ -85,8 +85,9 @@ analyze(llvm::ArrayRef ASTRoots, const auto MainFile = *SM.getFileEntryRefForID(SM.getMainFileID()); llvm::DenseSet Used; llvm::StringMap
Missing; + constexpr auto DefaultHeaderFilter = [](llvm::StringRef) { return false; }; if (!HeaderFilter) - HeaderFilter = [](llvm::StringRef) { return false; }; + HeaderFilter = DefaultHeaderFilter; OptionalDirectoryEntryRef ResourceDir = PP.getHeaderSearchInfo().getModuleMap().getBuiltinDir(); walkUsed(ASTRoots, MacroRefs, PI, PP, diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 12038de476ace..ffd157e60997c 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -355,10 +355,12 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver)) return 1; + auto ExecuteCC1WithContext = + [&ToolContext](SmallVectorImpl &ArgV) { + return ExecuteCC1Tool(ArgV, ToolContext); + }; if (!UseNewCC1Process) { - TheDriver.CC1Main = [ToolContext](SmallVectorImpl &ArgV) { - return ExecuteCC1Tool(ArgV, ToolContext); - }; + TheDriver.CC1Main = ExecuteCC1WithContext; // Ensure the CC1Command actually catches cc1 crashes llvm::CrashRecoveryContext::Enable(); } diff --git a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp index 0f2c889d4f390..4e02559a08949 100644 --- a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp @@ -919,8 +919,9 @@ static void generateUnrolledLoop( // 'forOp'. auto builder = OpBuilder::atBlockTerminator(loopBodyBlock); + constexpr auto defaultAnnotateFn = [](unsigned, Operation *, OpBuilder) {}; if (!annotateFn) - annotateFn = [](unsigned, Operation *, OpBuilder) {}; + annotateFn = defaultAnnotateFn; // Keep a pointer to the last non-terminator operation in the original block // so that we know what to clone (since we are doing this in-place). diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp index 41410a0a56aa9..6cda7100fe073 100644 --- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp +++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp @@ -329,8 +329,9 @@ static void generateUnrolledLoop( // 'forOp'. auto builder = OpBuilder::atBlockTerminator(loopBodyBlock); + constexpr auto defaultAnnotateFn = [](unsigned, Operation *, OpBuilder) {}; if (!annotateFn) - annotateFn = [](unsigned, Operation *, OpBuilder) {}; + annotateFn = defaultAnnotateFn; // Keep a pointer to the last non-terminator operation in the original block // so that we know what to clone (since we are doing this in-place). From 1411a9ae9358c7fc17e84876b82f6d2293c7ba4d Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 8 Jan 2025 08:50:50 -0500 Subject: [PATCH 017/163] [libc++][NFC] Add missing includes in tzdb.cpp --- libcxx/src/experimental/tzdb.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libcxx/src/experimental/tzdb.cpp b/libcxx/src/experimental/tzdb.cpp index d22de21c99819..638d45f69e033 100644 --- a/libcxx/src/experimental/tzdb.cpp +++ b/libcxx/src/experimental/tzdb.cpp @@ -9,11 +9,14 @@ // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html #include +#include #include #include #include #include #include +#include +#include #include "include/tzdb/time_zone_private.h" #include "include/tzdb/types_private.h" From 346fad5c2c28d0cd39475ae979ee468a420ebed7 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 8 Jan 2025 14:08:28 +0000 Subject: [PATCH 018/163] [TBAA] Simplify checks for unnamed struct case, where anyptr is used. --- clang/test/CodeGen/tbaa-pointers.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c index 0125d622faffa..4aae2552f107a 100644 --- a/clang/test/CodeGen/tbaa-pointers.c +++ b/clang/test/CodeGen/tbaa-pointers.c @@ -193,11 +193,10 @@ typedef struct { void unamed_struct_typedef(TypedefS *ptr) { // COMMON-LABEL: define void @unamed_struct_typedef( // COMMON-SAME: ptr noundef [[PTRA:%.+]]) -// COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 +// COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 // DISABLE-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] -// DISABLE-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] -// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF:!.+]] -// DEFAULT-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF]] +// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] +// COMMON-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: [[GEP:%.+]] = getelementptr inbounds nuw %struct.TypedefS, ptr [[L0]], i32 0, i32 0 // COMMON-NEXT: store i32 0, ptr [[GEP]], align 4 // COMMON-NEXT: ret void @@ -254,7 +253,7 @@ int void_ptrs(void **ptr) { // DISABLE: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} // COMMON: [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0} // COMMON: [[INT_TY]] = !{!"int", [[CHAR]], i64 0} -// DEFAULT: [[P1TYPEDEF]] = !{[[ANY_POINTER]], [[ANY_POINTER]], i64 0} +// DEFAULT: [[ANYPTR]] = !{[[ANY_POINTER]], [[ANY_POINTER]], i64 0} // DEFAULT: [[P2VOID]] = !{[[P2VOID_TY:!.+]], [[P2VOID_TY]], i64 0} // DEFAULT: [[P2VOID_TY]] = !{!"p2 void", [[ANY_POINTER]], i64 0} // DEFAULT: [[P1VOID]] = !{[[P1VOID_TY:!.+]], [[P1VOID_TY]], i64 0} From 59bdea24b09bca9332a7092b583ebf377efb0d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 8 Jan 2025 15:09:52 +0100 Subject: [PATCH 019/163] Revert "[clang] Avoid re-evaluating field bitwidth (#117732)" This reverts commit 81fc3add1e627c23b7270fe2739cdacc09063e54. This breaks some LLDB tests, e.g. SymbolFile/DWARF/x86/no_unique_address-with-bitfields.cpp: lldb: ../llvm-project/clang/lib/AST/Decl.cpp:4604: unsigned int clang::FieldDecl::getBitWidthValue() const: Assertion `isa(getBitWidth())' failed. --- .../bugprone/NarrowingConversionsCheck.cpp | 2 +- .../bugprone/TooSmallLoopVariableCheck.cpp | 2 +- .../hicpp/MultiwayPathsCoveredCheck.cpp | 2 +- clang-tools-extra/clangd/Hover.cpp | 2 +- clang/include/clang/AST/Decl.h | 6 ++---- clang/include/clang/ASTMatchers/ASTMatchers.h | 3 ++- clang/lib/AST/ASTContext.cpp | 10 ++++----- clang/lib/AST/ByteCode/Interp.h | 10 +++++---- .../lib/AST/ByteCode/InterpBuiltinBitCast.cpp | 8 +++---- clang/lib/AST/Decl.cpp | 16 +++++--------- clang/lib/AST/DeclCXX.cpp | 2 +- clang/lib/AST/Expr.cpp | 3 ++- clang/lib/AST/ExprConstant.cpp | 2 +- clang/lib/AST/Randstruct.cpp | 2 +- clang/lib/AST/RecordLayoutBuilder.cpp | 6 +++--- clang/lib/CodeGen/ABIInfo.cpp | 2 +- clang/lib/CodeGen/ABIInfoImpl.cpp | 2 +- clang/lib/CodeGen/CGCall.cpp | 6 +++--- clang/lib/CodeGen/CGClass.cpp | 2 +- clang/lib/CodeGen/CGDebugInfo.cpp | 8 ++++--- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 6 +++--- clang/lib/CodeGen/CGObjCMac.cpp | 3 ++- clang/lib/CodeGen/CGObjCRuntime.cpp | 2 +- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 20 +++++++++--------- clang/lib/CodeGen/SwiftCallingConv.cpp | 2 +- clang/lib/CodeGen/Targets/LoongArch.cpp | 2 +- clang/lib/CodeGen/Targets/RISCV.cpp | 2 +- clang/lib/CodeGen/Targets/X86.cpp | 2 +- clang/lib/CodeGen/Targets/XCore.cpp | 2 +- .../Frontend/Rewrite/RewriteModernObjC.cpp | 3 +-- clang/lib/Sema/SemaChecking.cpp | 10 ++++----- clang/lib/Sema/SemaDecl.cpp | 21 +++++++++---------- clang/lib/Sema/SemaDeclCXX.cpp | 6 +++--- clang/lib/Sema/SemaDeclObjC.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 2 +- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 2 +- clang/tools/libclang/CXType.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 4 ++-- 38 files changed, 94 insertions(+), 96 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp index 408390ebc70b6..a950704208c73 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp @@ -38,7 +38,7 @@ AST_MATCHER(FieldDecl, hasIntBitwidth) { assert(Node.isBitField()); const ASTContext &Ctx = Node.getASTContext(); unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy); - unsigned CurrentBitWidth = Node.getBitWidthValue(); + unsigned CurrentBitWidth = Node.getBitWidthValue(Ctx); return IntBitWidth == CurrentBitWidth; } diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp index 4ceeefb78ee82..a73d46f01d9b2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -124,7 +124,7 @@ static MagnitudeBits calcMagnitudeBits(const ASTContext &Context, unsigned SignedBits = IntExprType->isUnsignedIntegerType() ? 0U : 1U; if (const auto *BitField = IntExpr->getSourceBitField()) { - unsigned BitFieldWidth = BitField->getBitWidthValue(); + unsigned BitFieldWidth = BitField->getBitWidthValue(Context); return {BitFieldWidth - SignedBits, BitFieldWidth}; } diff --git a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp index 7028c3958f103..47dafca2d03ff 100644 --- a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp @@ -160,7 +160,7 @@ void MultiwayPathsCoveredCheck::handleSwitchWithoutDefault( } if (const auto *BitfieldDecl = Result.Nodes.getNodeAs("bitfield")) { - return twoPow(BitfieldDecl->getBitWidthValue()); + return twoPow(BitfieldDecl->getBitWidthValue(*Result.Context)); } return static_cast(0); diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 5e136d0e76ece..298fa79e3fd0b 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -1018,7 +1018,7 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Record); HI.Offset = Layout.getFieldOffset(FD->getFieldIndex()); if (FD->isBitField()) - HI.Size = FD->getBitWidthValue(); + HI.Size = FD->getBitWidthValue(Ctx); else if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FD->getType())) HI.Size = FD->isZeroSize(Ctx) ? 0 : Size->getQuantity() * 8; if (HI.Size) { diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 5670072ab4a76..67ee0bb412692 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3142,9 +3142,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { /// Computes the bit width of this field, if this is a bit field. /// May not be called on non-bitfields. - /// Note that in order to successfully use this function, the bitwidth - /// expression must be a ConstantExpr with a valid integer result set. - unsigned getBitWidthValue() const; + unsigned getBitWidthValue(const ASTContext &Ctx) const; /// Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). @@ -3175,7 +3173,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { /// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields /// at all and instead act as a separator between contiguous runs of other /// bit-fields. - bool isZeroLengthBitField() const; + bool isZeroLengthBitField(const ASTContext &Ctx) const; /// Determine if this field is a subobject of zero size, that is, either a /// zero-length bit-field or a field of empty class type with the diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index ef3d34d4123d8..f10135d7a901f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -708,7 +708,8 @@ AST_MATCHER(FieldDecl, isBitField) { /// fieldDecl(hasBitWidth(2)) /// matches 'int a;' and 'int c;' but not 'int b;'. AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { - return Node.isBitField() && Node.getBitWidthValue() == Width; + return Node.isBitField() && + Node.getBitWidthValue(Finder->getASTContext()) == Width; } /// Matches non-static data members that have an in-class initializer. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 46431634d9102..b10513f49a8d1 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2795,7 +2795,7 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context, if (Field->isUnnamedBitField()) return 0; - int64_t BitfieldSize = Field->getBitWidthValue(); + int64_t BitfieldSize = Field->getBitWidthValue(Context); if (IsBitIntType) { if ((unsigned)BitfieldSize > cast(Field->getType())->getNumBits()) @@ -7769,7 +7769,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { QualType FT = Field->getType(); - uint64_t BitWidth = Field->getBitWidthValue(); + uint64_t BitWidth = Field->getBitWidthValue(*this); uint64_t IntSize = getTypeSize(IntTy); // C++ [conv.prom]p5: // A prvalue for an integral bit-field can be converted to a prvalue of type @@ -8797,7 +8797,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += getObjCEncodingForPrimitiveType(Ctx, BT); } } - S += llvm::utostr(FD->getBitWidthValue()); + S += llvm::utostr(FD->getBitWidthValue(*Ctx)); } // Helper function for determining whether the encoded type string would include @@ -9223,7 +9223,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } for (FieldDecl *Field : RDecl->fields()) { - if (!Field->isZeroLengthBitField() && Field->isZeroSize(*this)) + if (!Field->isZeroLengthBitField(*this) && Field->isZeroSize(*this)) continue; uint64_t offs = layout.getFieldOffset(Field->getFieldIndex()); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), @@ -9320,7 +9320,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); #ifndef NDEBUG - CurOffs += field->getBitWidthValue(); + CurOffs += field->getBitWidthValue(*this); #endif } else { QualType qt = field->getType(); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 93a91976a31bf..d2aec69072e04 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1471,7 +1471,8 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, return false; const Pointer &Field = This.atField(FieldOffset); const auto &Value = S.Stk.pop(); - Field.deref() = Value.truncate(F->Decl->getBitWidthValue()); + Field.deref() = + Value.truncate(F->Decl->getBitWidthValue(S.getASTContext())); Field.initialize(); return true; } @@ -1494,7 +1495,8 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) { assert(F->isBitField()); const T &Value = S.Stk.pop(); const Pointer &Field = S.Stk.peek().atField(F->Offset); - Field.deref() = Value.truncate(F->Decl->getBitWidthValue()); + Field.deref() = + Value.truncate(F->Decl->getBitWidthValue(S.getASTContext())); Field.activate(); Field.initialize(); return true; @@ -1748,7 +1750,7 @@ bool StoreBitField(InterpState &S, CodePtr OpPC) { if (Ptr.canBeInitialized()) Ptr.initialize(); if (const auto *FD = Ptr.getField()) - Ptr.deref() = Value.truncate(FD->getBitWidthValue()); + Ptr.deref() = Value.truncate(FD->getBitWidthValue(S.getASTContext())); else Ptr.deref() = Value; return true; @@ -1763,7 +1765,7 @@ bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) { if (Ptr.canBeInitialized()) Ptr.initialize(); if (const auto *FD = Ptr.getField()) - Ptr.deref() = Value.truncate(FD->getBitWidthValue()); + Ptr.deref() = Value.truncate(FD->getBitWidthValue(S.getASTContext())); else Ptr.deref() = Value; return true; diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index f4c54551a9a60..57c1fab5d6ab4 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -269,7 +269,7 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx, Bits BitWidth = FullBitWidth; if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = Bits(std::min(FD->getBitWidthValue(), + BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), (unsigned)FullBitWidth.getQuantity())); else if (T == PT_Bool && PackedBools) BitWidth = Bits(1); @@ -301,8 +301,8 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx, assert(NumBits.isFullByte()); assert(NumBits.getQuantity() <= FullBitWidth.getQuantity()); F.bitcastToMemory(Buff.get()); - // Now, only (maybe) swap the actual size of the float, excluding - // the padding bits. + // Now, only (maybe) swap the actual size of the float, excluding the + // padding bits. if (llvm::sys::IsBigEndianHost) swapBytes(Buff.get(), NumBits.roundToBytes()); @@ -406,7 +406,7 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, Bits BitWidth; if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = Bits(std::min(FD->getBitWidthValue(), + BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx), (unsigned)FullBitWidth.getQuantity())); else if (T == PT_Bool && PackedBools) BitWidth = Bits(1); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 37baf06cc55dd..741e908cf9bc5 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4599,24 +4599,18 @@ void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) { Init = NewInit; } -unsigned FieldDecl::getBitWidthValue() const { +unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); - assert(isa(getBitWidth())); - assert(cast(getBitWidth())->hasAPValueResult()); - assert(cast(getBitWidth())->getAPValueResult().isInt()); - return cast(getBitWidth()) - ->getAPValueResult() - .getInt() - .getZExtValue(); + return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); } -bool FieldDecl::isZeroLengthBitField() const { +bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const { return isUnnamedBitField() && !getBitWidth()->isValueDependent() && - getBitWidthValue() == 0; + getBitWidthValue(Ctx) == 0; } bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { - if (isZeroLengthBitField()) + if (isZeroLengthBitField(Ctx)) return true; // C++2a [intro.object]p7: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 21e128f4a4a7d..af73c658d6a0c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -993,7 +993,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++ [meta.unary.prop]p4: [LWG2358] // T is a class type [...] with [...] no unnamed bit-fields of non-zero // length - if (data().Empty && !Field->isZeroLengthBitField() && + if (data().Empty && !Field->isZeroLengthBitField(Context) && Context.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6) data().Empty = false; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 5331357b5d1fe..ba66d36278567 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -196,7 +196,8 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { if (const FieldDecl *FD = E->getSourceBitField()) if (!Semantic && FD->getType()->isUnsignedIntegerType() && - !FD->getBitWidth()->isValueDependent() && FD->getBitWidthValue() == 1) + !FD->getBitWidth()->isValueDependent() && + FD->getBitWidthValue(FD->getASTContext()) == 1) return true; return false; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 716602a5d7c50..e220f69b3a4f5 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2875,7 +2875,7 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, APSInt &Int = Value.getInt(); unsigned OldBitWidth = Int.getBitWidth(); - unsigned NewBitWidth = FD->getBitWidthValue(); + unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); if (NewBitWidth < OldBitWidth) Int = Int.trunc(NewBitWidth).extend(OldBitWidth); return true; diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp index 4537ba5309e0b..b484afa4997bb 100644 --- a/clang/lib/AST/Randstruct.cpp +++ b/clang/lib/AST/Randstruct.cpp @@ -91,7 +91,7 @@ void randomizeStructureLayoutImpl(const ASTContext &Context, auto FieldIter = FieldsOut.begin(); FieldDecl *FD = *FieldIter; - if (FD->isBitField() && !FD->isZeroLengthBitField()) { + if (FD->isBitField() && !FD->isZeroLengthBitField(Context)) { // Start a bitfield run if this is the first bitfield we have found. if (!CurrentBitfieldRun) CurrentBitfieldRun = std::make_unique(); diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index e6af27e8c9677..f749d3a705fc9 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1542,7 +1542,7 @@ static bool isAIXLayout(const ASTContext &Context) { void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr(); - uint64_t FieldSize = D->getBitWidthValue(); + uint64_t FieldSize = D->getBitWidthValue(Context); TypeInfo FieldInfo = Context.getTypeInfo(D->getType()); uint64_t StorageUnitSize = FieldInfo.Width; unsigned FieldAlign = FieldInfo.Align; @@ -3022,7 +3022,7 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { } void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { - unsigned Width = FD->getBitWidthValue(); + unsigned Width = FD->getBitWidthValue(Context); if (Width == 0) { layoutZeroWidthBitField(FD); return; @@ -3692,7 +3692,7 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, if (Field.isBitField()) { uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset); unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits; - unsigned Width = Field.getBitWidthValue(); + unsigned Width = Field.getBitWidthValue(C); PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel); } else { PrintOffset(OS, FieldOffset, IndentLevel); diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index 642bca9e8b76d..8e76cf15b642c 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -106,7 +106,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, continue; if (isZeroLengthBitfieldPermittedInHomogeneousAggregate() && - FD->isZeroLengthBitField()) + FD->isZeroLengthBitField(getContext())) continue; uint64_t FldMembers; diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 795874059bda7..79300df15d0e2 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -303,7 +303,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD) { - if (FD->isZeroLengthBitField()) + if (FD->isZeroLengthBitField(Context)) return true; if (FD->isUnnamedBitField()) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d497fcff37f87..7b0ef4be98619 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -954,7 +954,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { CharUnits UnionSize = CharUnits::Zero(); for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField()) + if (FD->isZeroLengthBitField(Context)) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -974,7 +974,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { } for (const auto *FD : RD->fields()) { - if (FD->isZeroLengthBitField()) + if (FD->isZeroLengthBitField(Context)) continue; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -3682,7 +3682,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) { const FieldDecl *F = *I; - if (F->isUnnamedBitField() || F->isZeroLengthBitField() || + if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) || F->getType()->isIncompleteArrayType()) continue; diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 8c190732c8cdc..c45688bd1ed3c 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -945,7 +945,7 @@ namespace { ASTContext &Ctx = CGF.getContext(); unsigned LastFieldSize = LastField->isBitField() - ? LastField->getBitWidthValue() + ? LastField->getBitWidthValue(Ctx) : Ctx.toBits( Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width); uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize - diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d7e5e95b7873a..560d4ce293365 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1721,7 +1721,8 @@ llvm::DIDerivedType *CGDebugInfo::createBitFieldSeparatorIfNeeded( assert(PreviousBitfield->isBitField()); - if (!PreviousBitfield->isZeroLengthBitField()) + ASTContext &Context = CGM.getContext(); + if (!PreviousBitfield->isZeroLengthBitField(Context)) return nullptr; QualType Ty = PreviousBitfield->getType(); @@ -3213,8 +3214,9 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. - FieldSize = Field->isBitField() ? Field->getBitWidthValue() - : CGM.getContext().getTypeSize(FType); + FieldSize = Field->isBitField() + ? Field->getBitWidthValue(CGM.getContext()) + : CGM.getContext().getTypeSize(FType); FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); } diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index d90c44d770d14..6a02e4dbf84d1 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -25,7 +25,7 @@ using namespace CodeGen; static uint64_t getFieldSize(const FieldDecl *FD, QualType FT, ASTContext &Ctx) { if (FD && FD->isBitField()) - return FD->getBitWidthValue(); + return FD->getBitWidthValue(Ctx); return Ctx.getTypeSize(FT); } @@ -255,7 +255,7 @@ struct GenBinaryFuncName : CopyStructVisitor, IsMove>, void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset) { // Zero-length bit-fields don't need to be copied/assigned. - if (FD && FD->isZeroLengthBitField()) + if (FD && FD->isZeroLengthBitField(this->Ctx)) return; // Because volatile fields can be bit-fields and are individually copied, @@ -544,7 +544,7 @@ struct GenBinaryFunc : CopyStructVisitor, LValue DstLV, SrcLV; if (FD) { // No need to copy zero-length bit-fields. - if (FD->isZeroLengthBitField()) + if (FD->isZeroLengthBitField(this->CGF->getContext())) return; QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index dd900f9b32fb7..7b85dcc2c7984 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2543,7 +2543,8 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (LastFieldBitfieldOrUnnamed) { if (LastFieldBitfieldOrUnnamed->isBitField()) { // Last field was a bitfield. Must update the info. - uint64_t BitFieldSize = LastFieldBitfieldOrUnnamed->getBitWidthValue(); + uint64_t BitFieldSize + = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + ((BitFieldSize % ByteSizeInBits) != 0); CharUnits Size = CharUnits::fromQuantity(UnsSize); diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index b438a92a4fd62..01d0f35da1964 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -89,7 +89,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); - uint64_t BitFieldSize = Ivar->getBitWidthValue(); + uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits)); CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 4afcd9d6d32cc..ea44e6f21f3c8 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -148,8 +148,8 @@ struct CGRecordLowering { llvm::Type *Type = Types.ConvertTypeForMem(FD->getType()); if (!FD->isBitField()) return Type; if (isDiscreteBitFieldABI()) return Type; - return getIntNType(std::min(FD->getBitWidthValue(), - (unsigned)Context.toBits(getSize(Type)))); + return getIntNType(std::min(FD->getBitWidthValue(Context), + (unsigned)Context.toBits(getSize(Type)))); } /// Gets the llvm Basesubobject type from a CXXRecordDecl. llvm::Type *getStorageType(const CXXRecordDecl *RD) const { @@ -242,7 +242,7 @@ void CGRecordLowering::setBitFieldInfo( CGBitFieldInfo &Info = BitFields[FD->getCanonicalDecl()]; Info.IsSigned = FD->getType()->isSignedIntegerOrEnumerationType(); Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset)); - Info.Size = FD->getBitWidthValue(); + Info.Size = FD->getBitWidthValue(Context); Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType); Info.StorageOffset = StartOffset; if (Info.Size > Info.StorageSize) @@ -322,7 +322,7 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { // been doing and cause lit tests to change. for (const auto *Field : D->fields()) { if (Field->isBitField()) { - if (Field->isZeroLengthBitField()) + if (Field->isZeroLengthBitField(Context)) continue; llvm::Type *FieldType = getStorageType(Field); if (LayoutSize < getSize(FieldType)) @@ -423,7 +423,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, uint64_t StartBitOffset, Tail = 0; for (; Field != FieldEnd && Field->isBitField(); ++Field) { // Zero-width bitfields end runs. - if (Field->isZeroLengthBitField()) { + if (Field->isZeroLengthBitField(Context)) { Run = FieldEnd; continue; } @@ -559,7 +559,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, // Bitfield potentially begins a new span. This includes zero-length // bitfields on non-aligning targets that lie at character boundaries // (those are barriers to merging). - if (Field->isZeroLengthBitField()) + if (Field->isZeroLengthBitField(Context)) Barrier = true; AtAlignedBoundary = true; } @@ -697,7 +697,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, } Members.push_back(StorageInfo(BeginOffset, Type)); for (; Begin != BestEnd; ++Begin) - if (!Begin->isZeroLengthBitField()) + if (!Begin->isZeroLengthBitField(Context)) Members.push_back( MemberInfo(BeginOffset, MemberInfo::Field, nullptr, *Begin)); } @@ -709,7 +709,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, "Accumulating past end of bitfields"); assert(!Barrier && "Accumulating across barrier"); // Accumulate this bitfield into the current (potential) span. - BitSizeSinceBegin += Field->getBitWidthValue(); + BitSizeSinceBegin += Field->getBitWidthValue(Context); ++Field; } } @@ -813,7 +813,7 @@ void CGRecordLowering::computeVolatileBitfields() { bool Conflict = false; for (const auto *F : D->fields()) { // Allow sized bit-fields overlaps. - if (F->isBitField() && !F->isZeroLengthBitField()) + if (F->isBitField() && !F->isZeroLengthBitField(Context)) continue; const CharUnits FOffset = Context.toCharUnitsFromBits( @@ -823,7 +823,7 @@ void CGRecordLowering::computeVolatileBitfields() { // fields after and before it should be race condition free. // The AAPCS acknowledges it and imposes no restritions when the // natural container overlaps a zero-length bit-field. - if (F->isZeroLengthBitField()) { + if (F->isZeroLengthBitField(Context)) { if (End > FOffset && StorageOffset < FOffset) { Conflict = true; break; diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 1ff4ece2811ec..0873896df213e 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -186,7 +186,7 @@ void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield, uint64_t bitfieldBitBegin) { assert(bitfield->isBitField()); auto &ctx = CGM.getContext(); - auto width = bitfield->getBitWidthValue(); + auto width = bitfield->getBitWidthValue(ctx); // We can ignore zero-width bit-fields. if (width == 0) return; diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 6c90e48a5ea41..6af9375461f09 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -192,7 +192,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( for (const FieldDecl *FD : RD->fields()) { QualType QTy = FD->getType(); if (FD->isBitField()) { - unsigned BitWidth = FD->getBitWidthValue(); + unsigned BitWidth = FD->getBitWidthValue(getContext()); // Zero-width bitfields are ignored. if (BitWidth == 0) continue; diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 2b70f2bd3f38b..873e696e1328f 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -246,7 +246,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex()); QualType QTy = FD->getType(); if (FD->isBitField()) { - unsigned BitWidth = FD->getBitWidthValue(); + unsigned BitWidth = FD->getBitWidthValue(getContext()); // Allow a bitfield with a type greater than XLen as long as the // bitwidth is XLen or less. if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 5ee5179dd0f3e..7f73bf2a65266 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2130,7 +2130,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, if (BitField) { assert(!i->isUnnamedBitField()); uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - uint64_t Size = i->getBitWidthValue(); + uint64_t Size = i->getBitWidthValue(getContext()); uint64_t EB_Lo = Offset / 64; uint64_t EB_Hi = (Offset + Size - 1) / 64; diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index ced4981fd124f..f3e241171b872 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -343,7 +343,7 @@ static bool extractFieldType(SmallVectorImpl &FE, if (Field->isBitField()) { Enc += "b("; llvm::raw_svector_ostream OS(Enc); - OS << Field->getBitWidthValue(); + OS << Field->getBitWidthValue(CGM.getContext()); Enc += ':'; } if (!appendType(Enc, Field->getType(), CGM, TSC)) diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index fc65559e9d4a5..8cdb463e2c99f 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -3699,8 +3699,7 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Type.getAsStringInternal(Name, Context->getPrintingPolicy()); Result += Name; if (fieldDecl->isBitField()) { - Result += " : "; - Result += utostr(fieldDecl->getBitWidthValue()); + Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); } else if (EleboratedType && Type->isArrayType()) { const ArrayType *AT = Context->getAsArrayType(Type); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 881907ac311a3..28dcfaac2e84f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -658,7 +658,7 @@ struct BuiltinDumpStructGenerator { Format += ": %zu "; QualType SizeT = S.Context.getSizeType(); llvm::APInt BitWidth(S.Context.getIntWidth(SizeT), - FD->getBitWidthValue()); + FD->getBitWidthValue(S.Context)); Args.push_back(IntegerLiteral::Create(S.Context, BitWidth, SizeT, Loc)); } @@ -10027,7 +10027,7 @@ static std::optional TryGetExprRange(ASTContext &C, const Expr *E, Approximate); if (const auto *BitField = E->getSourceBitField()) - return IntRange(BitField->getBitWidthValue(), + return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); if (GetExprType(E)->isVoidType()) @@ -10580,7 +10580,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, return false; Expr *OriginalInit = Init->IgnoreParenImpCasts(); - unsigned FieldWidth = Bitfield->getBitWidthValue(); + unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); Expr::EvalResult Result; if (!OriginalInit->EvaluateAsInt(Result, S.Context, @@ -14044,8 +14044,8 @@ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1, if (Field1->isBitField()) { // Make sure that the bit-fields are the same length. - unsigned Bits1 = Field1->getBitWidthValue(); - unsigned Bits2 = Field2->getBitWidthValue(); + unsigned Bits1 = Field1->getBitWidthValue(C); + unsigned Bits2 = Field2->getBitWidthValue(C); if (Bits1 != Bits2) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9f9510a6ab275..4001c4d263f1d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18376,9 +18376,7 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, } } - if (isa(BitWidth)) - return BitWidth; - return ConstantExpr::Create(getASTContext(), BitWidth, APValue{Value}); + return BitWidth; } Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, @@ -18753,7 +18751,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast(ivarDecl); - if (!Ivar->isBitField() || Ivar->isZeroLengthBitField()) + if (!Ivar->isBitField() || Ivar->isZeroLengthBitField(Context)) return; ObjCInterfaceDecl *ID = dyn_cast(CurContext); if (!ID) { @@ -18768,13 +18766,14 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, // All conditions are met. Add a new bitfield to the tail end of ivars. llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); - Expr *BitWidth = - ConstantExpr::Create(Context, BW, APValue(llvm::APSInt(Zero))); - Ivar = ObjCIvarDecl::Create( - Context, cast(CurContext), DeclLoc, DeclLoc, nullptr, - Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy, DeclLoc), - ObjCIvarDecl::Private, BitWidth, true); + Ivar = ObjCIvarDecl::Create(Context, cast(CurContext), + DeclLoc, DeclLoc, nullptr, + Context.CharTy, + Context.getTrivialTypeSourceInfo(Context.CharTy, + DeclLoc), + ObjCIvarDecl::Private, BW, + true); AllIvarDecls.push_back(Ivar); } @@ -19404,7 +19403,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; if (I->isUnnamedBitField()) { - if (!I->isZeroLengthBitField()) + if (!I->isZeroLengthBitField(Context)) ZeroSize = false; } else { ++NonBitFields; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c4bee44f5ec04..c5a72cf812ebc 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4877,7 +4877,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. - if (Field->isZeroLengthBitField()) + if (Field->isZeroLengthBitField(SemaRef.Context)) return false; Expr *MemberExprBase = @@ -15041,7 +15041,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isZeroLengthBitField()) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType(); @@ -15428,7 +15428,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } // Suppress assigning zero-width bitfields. - if (Field->isZeroLengthBitField()) + if (Field->isZeroLengthBitField(Context)) continue; QualType FieldType = Field->getType().getNonReferenceType(); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index f97f17e8c9658..6e6174ba17c55 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2210,7 +2210,8 @@ void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, << ImplIvar->getType() << ClsIvar->getType(); Diag(ClsIvar->getLocation(), diag::note_previous_definition); } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && - ImplIvar->getBitWidthValue() != ClsIvar->getBitWidthValue()) { + ImplIvar->getBitWidthValue(Context) != + ClsIvar->getBitWidthValue(Context)) { Diag(ImplIvar->getBitWidth()->getBeginLoc(), diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 75a6d2b6a1dbb..7589701fb81de 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -516,7 +516,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (const FieldDecl *BitField = Initializer->getSourceBitField()) { if (BitField->getBitWidth()->isValueDependent()) DependentBitField = true; - else if (unsigned BitFieldWidth = BitField->getBitWidthValue(); + else if (unsigned BitFieldWidth = BitField->getBitWidthValue(Ctx); BitFieldWidth < FromWidth) { if (CanRepresentAll(FromSigned, BitFieldWidth, ToSigned, ToWidth)) return NK_Not_Narrowing; diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 6266878565c52..ad45ab5757a5a 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -931,7 +931,7 @@ collectSubRegionBindings(SmallVectorImpl &Bindings, Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth(); } else if (const FieldRegion *FR = dyn_cast(Top)) { if (FR->getDecl()->isBitField()) - Length = FR->getDecl()->getBitWidthValue(); + Length = FR->getDecl()->getBitWidthValue(SVB.getContext()); } for (const auto &StoreEntry : Cluster) { diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 990daadd322dc..b4df12405cf35 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -381,7 +381,7 @@ int clang_getFieldDeclBitWidth(CXCursor C) { if (const FieldDecl *FD = dyn_cast_or_null(D)) { if (FD->isBitField() && !FD->getBitWidth()->isValueDependent()) - return FD->getBitWidthValue(); + return FD->getBitWidthValue(getCursorContext(C)); } } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index ef76ee80d7c7b..d197d30df3adf 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -3392,12 +3392,12 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) { FirstDeclMatcher().match(FromTU, fieldDecl(hasName("x"))); ASSERT_TRUE(FromF->isBitField()); - ASSERT_EQ(3u, FromF->getBitWidthValue()); + ASSERT_EQ(3u, FromF->getBitWidthValue(FromTU->getASTContext())); auto *ToField = Import(FromF, Lang_CXX03); auto *ToTU = ToField->getTranslationUnitDecl(); EXPECT_TRUE(ToField->isBitField()); - EXPECT_EQ(3u, ToField->getBitWidthValue()); + EXPECT_EQ(3u, ToField->getBitWidthValue(ToTU->getASTContext())); const auto *FromBT = FromF->getBitWidth()->getType()->getAs(); const auto *ToBT = ToField->getBitWidth()->getType()->getAs(); From 0d7022ed75ef4d1efdfbdbf206e3f4041a9cd18b Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 8 Jan 2025 15:17:15 +0100 Subject: [PATCH 020/163] [MLIR][GPU] Fix gpu.printf test syntax after f50f9698ad012882df8dd605f5482e280c138266 --- .../Integration/GPU/CUDA/sm90/tma_load_64x64_swizzle128b.mlir | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlir/test/Integration/GPU/CUDA/sm90/tma_load_64x64_swizzle128b.mlir b/mlir/test/Integration/GPU/CUDA/sm90/tma_load_64x64_swizzle128b.mlir index fce16f3df2368..e76fa03903b8a 100644 --- a/mlir/test/Integration/GPU/CUDA/sm90/tma_load_64x64_swizzle128b.mlir +++ b/mlir/test/Integration/GPU/CUDA/sm90/tma_load_64x64_swizzle128b.mlir @@ -129,9 +129,9 @@ module @mymod { scf.for %j = %c0 to %c128 step %c1 { %lhs0 = memref.load %rhsShmem[%ii, %j] : !shmemrhs %lhs032 = arith.extf %lhs0: f16 to f32 - gpu.printf "%.0f, " %lhs032 : f32 + gpu.printf "%.0f, ", %lhs032 : f32 } - gpu.printf "%d\n" %c-1_i32 : i32 + gpu.printf "%d\n", %c-1_i32 : i32 } gpu.printf "===----------------=== %d \n", %c-1_i32 : i32 } From fdd7cafb9078e146634a3fbb72a8949108dca425 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Wed, 8 Jan 2025 09:40:56 -0500 Subject: [PATCH 021/163] [z/OS][SystemZ] Clang dependency files are text files (#121849) The dependency file and the P1689 file are text files, but the open call misses the OF_Text flag. This PR adds the flag. Fixes regressions in test cases ClangScanDeps/modules-extern-unrelated.m and ClangScanDeps/P1689.cppm. --- clang/tools/clang-scan-deps/ClangScanDeps.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index bd36181fca3f3..709dc513be281 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -913,7 +913,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { return llvm::nulls(); std::error_code EC; - FileOS.emplace(OutputFileName, EC); + FileOS.emplace(OutputFileName, EC, llvm::sys::fs::OF_Text); if (EC) { llvm::errs() << "Failed to open output file '" << OutputFileName << "': " << llvm::errorCodeToError(EC) << '\n'; @@ -1003,9 +1003,9 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { auto OSIter = OSs.find(MakeformatOutputPath); if (OSIter == OSs.end()) { std::error_code EC; - OSIter = - OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath, EC) - .first; + OSIter = OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath, + EC, llvm::sys::fs::OF_Text) + .first; if (EC) llvm::errs() << "Failed to open P1689 make format output file \"" << MakeformatOutputPath << "\" for " << EC.message() From 1160994602b90890efd4df4e134e46cc3ad34bc8 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 8 Jan 2025 06:06:43 -0800 Subject: [PATCH 022/163] [SLP]Fix a crash for very long GEP chains Need to check if the GEP bases are equal and return false early. Also, need to return false if the lookup is too deep, considering bases equal too. Fixes a crash in the assertion. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 7 +- .../SLPVectorizer/RISCV/long-gep-chains.ll | 76 +++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/RISCV/long-gep-chains.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index c4582df89213d..894dc68b6146d 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -5355,11 +5355,10 @@ static bool clusterSortPtrAccesses(ArrayRef VL, SmallPtrSet SecondPointers; Value *P1 = Ptr1; Value *P2 = Ptr2; - if (P1 == P2) - return false; unsigned Depth = 0; - while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1) && - Depth <= RecursionMaxDepth) { + while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1)) { + if (P1 == P2 || Depth > RecursionMaxDepth) + return false; FirstPointers.insert(P1); SecondPointers.insert(P2); P1 = getUnderlyingObject(P1, /*MaxLookup=*/1); diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/long-gep-chains.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/long-gep-chains.ll new file mode 100644 index 0000000000000..cf1ed54149b8b --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/long-gep-chains.ll @@ -0,0 +1,76 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=slp-vectorizer -mtriple=riscv64-unknown-linux -mattr=+v < %s | FileCheck %s + +define i64 @test(ptr %arg, i32 %arg1, i64 %i) { +; CHECK-LABEL: define i64 @test( +; CHECK-SAME: ptr [[ARG:%.*]], i32 [[ARG1:%.*]], i64 [[I:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[BB:.*:]] +; CHECK-NEXT: [[I2:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[I]] +; CHECK-NEXT: [[I3:%.*]] = getelementptr i8, ptr [[I2]], i64 [[I]] +; CHECK-NEXT: [[I4:%.*]] = getelementptr i8, ptr [[I3]], i64 [[I]] +; CHECK-NEXT: [[I5:%.*]] = getelementptr i8, ptr [[I4]], i64 [[I]] +; CHECK-NEXT: [[I6:%.*]] = getelementptr i8, ptr [[I5]], i64 [[I]] +; CHECK-NEXT: [[I7:%.*]] = getelementptr i8, ptr [[I6]], i64 [[I]] +; CHECK-NEXT: [[I8:%.*]] = getelementptr i8, ptr [[I7]], i64 [[I]] +; CHECK-NEXT: [[I9:%.*]] = getelementptr i8, ptr [[I8]], i64 [[I]] +; CHECK-NEXT: [[I10:%.*]] = getelementptr i8, ptr [[I9]], i64 [[I]] +; CHECK-NEXT: [[I11:%.*]] = getelementptr i8, ptr [[I10]], i64 [[I]] +; CHECK-NEXT: [[I12:%.*]] = getelementptr i8, ptr [[I11]], i64 [[I]] +; CHECK-NEXT: [[I13:%.*]] = getelementptr i8, ptr [[I12]], i64 [[I]] +; CHECK-NEXT: [[I14:%.*]] = getelementptr i8, ptr [[I13]], i64 [[I]] +; CHECK-NEXT: [[I140:%.*]] = load i8, ptr [[I14]], align 1 +; CHECK-NEXT: [[I1412:%.*]] = zext i8 [[I140]] to i32 +; CHECK-NEXT: [[I142:%.*]] = mul i32 [[ARG1]], [[I1412]] +; CHECK-NEXT: [[I143:%.*]] = getelementptr i8, ptr [[I13]], i64 15 +; CHECK-NEXT: [[I144:%.*]] = load i8, ptr [[I143]], align 1 +; CHECK-NEXT: [[I1453:%.*]] = zext i8 [[I144]] to i32 +; CHECK-NEXT: [[I146:%.*]] = mul i32 [[ARG1]], [[I1453]] +; CHECK-NEXT: [[I147:%.*]] = getelementptr i8, ptr [[I13]], i64 14 +; CHECK-NEXT: [[I148:%.*]] = load i8, ptr [[I147]], align 1 +; CHECK-NEXT: [[I1494:%.*]] = zext i8 [[I148]] to i32 +; CHECK-NEXT: [[I150:%.*]] = mul i32 [[ARG1]], [[I1494]] +; CHECK-NEXT: [[I151:%.*]] = getelementptr i8, ptr [[I13]], i64 13 +; CHECK-NEXT: [[I152:%.*]] = load i8, ptr [[I151]], align 1 +; CHECK-NEXT: [[I1535:%.*]] = zext i8 [[I152]] to i32 +; CHECK-NEXT: [[I154:%.*]] = mul i32 [[ARG1]], [[I1535]] +; CHECK-NEXT: [[I1311:%.*]] = or i32 [[I142]], [[I146]] +; CHECK-NEXT: [[I1312:%.*]] = or i32 [[I1311]], [[I150]] +; CHECK-NEXT: [[I1313:%.*]] = or i32 [[I1312]], [[I154]] +; CHECK-NEXT: [[I1536:%.*]] = zext i32 [[I1313]] to i64 +; CHECK-NEXT: ret i64 [[I1536]] +; +bb: + %i2 = getelementptr i8, ptr %arg, i64 %i + %i3 = getelementptr i8, ptr %i2, i64 %i + %i4 = getelementptr i8, ptr %i3, i64 %i + %i5 = getelementptr i8, ptr %i4, i64 %i + %i6 = getelementptr i8, ptr %i5, i64 %i + %i7 = getelementptr i8, ptr %i6, i64 %i + %i8 = getelementptr i8, ptr %i7, i64 %i + %i9 = getelementptr i8, ptr %i8, i64 %i + %i10 = getelementptr i8, ptr %i9, i64 %i + %i11 = getelementptr i8, ptr %i10, i64 %i + %i12 = getelementptr i8, ptr %i11, i64 %i + %i13 = getelementptr i8, ptr %i12, i64 %i + %i14 = getelementptr i8, ptr %i13, i64 %i + %i140 = load i8, ptr %i14, align 1 + %i1412 = zext i8 %i140 to i32 + %i142 = mul i32 %arg1, %i1412 + %i143 = getelementptr i8, ptr %i13, i64 15 + %i144 = load i8, ptr %i143, align 1 + %i1453 = zext i8 %i144 to i32 + %i146 = mul i32 %arg1, %i1453 + %i147 = getelementptr i8, ptr %i13, i64 14 + %i148 = load i8, ptr %i147, align 1 + %i1494 = zext i8 %i148 to i32 + %i150 = mul i32 %arg1, %i1494 + %i151 = getelementptr i8, ptr %i13, i64 13 + %i152 = load i8, ptr %i151, align 1 + %i1535 = zext i8 %i152 to i32 + %i154 = mul i32 %arg1, %i1535 + %i1311 = or i32 %i142, %i146 + %i1312 = or i32 %i1311, %i150 + %i1313 = or i32 %i1312, %i154 + %i1536 = zext i32 %i1313 to i64 + ret i64 %i1536 +} From 81898ac00e04ed3f352534a810829bdf4e6e14b7 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 8 Jan 2025 15:49:46 +0100 Subject: [PATCH 023/163] Revert "[lldb-dap] Ensure the IO forwarding threads are managed by the DAP object lifecycle. (#120457)" This reverts commit 0d9cf2671e06c9124a0b5fc753330c39c8b4a791. Breaks the lldb-aarch64-windows buildbot. --- lldb/tools/lldb-dap/CMakeLists.txt | 9 +- lldb/tools/lldb-dap/DAP.cpp | 105 ++++---------- lldb/tools/lldb-dap/DAP.h | 67 ++++----- lldb/tools/lldb-dap/IOStream.h | 6 - lldb/tools/lldb-dap/OutputRedirector.cpp | 76 ++++------ lldb/tools/lldb-dap/OutputRedirector.h | 34 +---- lldb/tools/lldb-dap/lldb-dap.cpp | 174 ++++++++--------------- 7 files changed, 157 insertions(+), 314 deletions(-) diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index 43fc18873feb3..d68098bf7b326 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -1,3 +1,7 @@ +if ( CMAKE_SYSTEM_NAME MATCHES "Windows" OR CMAKE_SYSTEM_NAME MATCHES "NetBSD" ) + list(APPEND extra_libs lldbHost) +endif () + if (HAVE_LIBPTHREAD) list(APPEND extra_libs pthread) endif () @@ -22,11 +26,9 @@ add_lldb_tool(lldb-dap lldb-dap.cpp Breakpoint.cpp BreakpointBase.cpp - DAP.cpp ExceptionBreakpoint.cpp FifoFiles.cpp FunctionBreakpoint.cpp - InstructionBreakpoint.cpp IOStream.cpp JSONUtils.cpp LLDBUtils.cpp @@ -34,11 +36,12 @@ add_lldb_tool(lldb-dap ProgressEvent.cpp RunInTerminal.cpp SourceBreakpoint.cpp + DAP.cpp Watchpoint.cpp + InstructionBreakpoint.cpp LINK_LIBS liblldb - lldbHost ${extra_libs} LINK_COMPONENTS diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index a67abe582abd4..35250d9eef608 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -6,62 +6,34 @@ // //===----------------------------------------------------------------------===// +#include +#include +#include +#include + #include "DAP.h" #include "JSONUtils.h" #include "LLDBUtils.h" -#include "OutputRedirector.h" -#include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBLanguageRuntime.h" #include "lldb/API/SBListener.h" -#include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-defines.h" -#include "lldb/lldb-enumerations.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include -#include -#include #if defined(_WIN32) #define NOMINMAX #include #include #include -#else -#include #endif using namespace lldb_dap; -namespace { -#ifdef _WIN32 -const char DEV_NULL[] = "nul"; -#else -const char DEV_NULL[] = "/dev/null"; -#endif -} // namespace - namespace lldb_dap { -DAP::DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, - StreamDescriptor input, StreamDescriptor output) - : debug_adaptor_path(path), log(log), input(std::move(input)), - output(std::move(output)), broadcaster("lldb-dap"), +DAP::DAP(llvm::StringRef path, ReplMode repl_mode) + : debug_adaptor_path(path), broadcaster("lldb-dap"), exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false), enable_auto_variable_summaries(false), @@ -71,7 +43,21 @@ DAP::DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, configuration_done_sent(false), waiting_for_run_in_terminal(false), progress_event_reporter( [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }), - reverse_request_seq(0), repl_mode(repl_mode) {} + reverse_request_seq(0), repl_mode(repl_mode) { + const char *log_file_path = getenv("LLDBDAP_LOG"); +#if defined(_WIN32) + // Windows opens stdout and stdin in text mode which converts \n to 13,10 + // while the value is just 10 on Darwin/Linux. Setting the file mode to binary + // fixes this. + int result = _setmode(fileno(stdout), _O_BINARY); + assert(result); + result = _setmode(fileno(stdin), _O_BINARY); + UNUSED_IF_ASSERT_DISABLED(result); + assert(result); +#endif + if (log_file_path) + log.reset(new std::ofstream(log_file_path)); +} DAP::~DAP() = default; @@ -187,45 +173,6 @@ ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) { return nullptr; } -llvm::Error DAP::ConfigureIO(std::FILE *overrideOut, std::FILE *overrideErr) { - in = lldb::SBFile(std::fopen(DEV_NULL, "r"), /*transfer_ownership=*/true); - - if (auto Error = out.RedirectTo([this](llvm::StringRef output) { - SendOutput(OutputType::Stdout, output); - })) - return Error; - - if (overrideOut) { - auto fd = out.GetWriteFileDescriptor(); - if (auto Error = fd.takeError()) - return Error; - - if (dup2(*fd, fileno(overrideOut)) == -1) - return llvm::errorCodeToError(llvm::errnoAsErrorCode()); - } - - if (auto Error = err.RedirectTo([this](llvm::StringRef output) { - SendOutput(OutputType::Stderr, output); - })) - return Error; - - if (overrideErr) { - auto fd = err.GetWriteFileDescriptor(); - if (auto Error = fd.takeError()) - return Error; - - if (dup2(*fd, fileno(overrideErr)) == -1) - return llvm::errorCodeToError(llvm::errnoAsErrorCode()); - } - - return llvm::Error::success(); -} - -void DAP::StopIO() { - out.Stop(); - err.Stop(); -} - // Send the JSON in "json_str" to the "out" stream. Correctly send the // "Content-Length:" field followed by the length, followed by the raw // JSON bytes. @@ -261,19 +208,19 @@ std::string DAP::ReadJSON() { std::string json_str; int length; - if (!input.read_expected(log, "Content-Length: ")) + if (!input.read_expected(log.get(), "Content-Length: ")) return json_str; - if (!input.read_line(log, length_str)) + if (!input.read_line(log.get(), length_str)) return json_str; if (!llvm::to_integer(length_str, length)) return json_str; - if (!input.read_expected(log, "\r\n")) + if (!input.read_expected(log.get(), "\r\n")) return json_str; - if (!input.read_full(log, length, json_str)) + if (!input.read_full(log.get(), length, json_str)) return json_str; if (log) { diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index 846300cb945b0..ae496236f1336 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -9,38 +9,36 @@ #ifndef LLDB_TOOLS_LLDB_DAP_DAP_H #define LLDB_TOOLS_LLDB_DAP_DAP_H -#include "DAPForward.h" -#include "ExceptionBreakpoint.h" -#include "FunctionBreakpoint.h" -#include "IOStream.h" -#include "InstructionBreakpoint.h" -#include "OutputRedirector.h" -#include "ProgressEvent.h" -#include "SourceBreakpoint.h" -#include "lldb/API/SBBroadcaster.h" -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBError.h" -#include "lldb/API/SBFile.h" -#include "lldb/API/SBFormat.h" -#include "lldb/API/SBFrame.h" -#include "lldb/API/SBTarget.h" -#include "lldb/API/SBThread.h" -#include "lldb/API/SBValue.h" -#include "lldb/API/SBValueList.h" -#include "lldb/lldb-types.h" +#include +#include +#include +#include +#include + #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" #include "llvm/Support/JSON.h" #include "llvm/Support/Threading.h" -#include -#include -#include -#include -#include +#include "llvm/Support/raw_ostream.h" + +#include "lldb/API/SBAttachInfo.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBFormat.h" +#include "lldb/API/SBLaunchInfo.h" +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBThread.h" + +#include "ExceptionBreakpoint.h" +#include "FunctionBreakpoint.h" +#include "IOStream.h" +#include "InstructionBreakpoint.h" +#include "ProgressEvent.h" +#include "SourceBreakpoint.h" #define VARREF_LOCALS (int64_t)1 #define VARREF_GLOBALS (int64_t)2 @@ -140,18 +138,15 @@ struct SendEventRequestHandler : public lldb::SBCommandPluginInterface { struct DAP { llvm::StringRef debug_adaptor_path; - std::ofstream *log; InputStream input; OutputStream output; - lldb::SBFile in; - OutputRedirector out; - OutputRedirector err; lldb::SBDebugger debugger; lldb::SBTarget target; Variables variables; lldb::SBBroadcaster broadcaster; std::thread event_thread; std::thread progress_event_thread; + std::unique_ptr log; llvm::StringMap source_breakpoints; FunctionBreakpointMap function_breakpoints; InstructionBreakpointMap instruction_breakpoints; @@ -203,23 +198,13 @@ struct DAP { // will contain that expression. std::string last_nonempty_var_expression; - DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, - StreamDescriptor input, StreamDescriptor output); + DAP(llvm::StringRef path, ReplMode repl_mode); ~DAP(); DAP(const DAP &rhs) = delete; void operator=(const DAP &rhs) = delete; ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter); ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id); - /// Redirect stdout and stderr fo the IDE's console output. - /// - /// Errors in this operation will be printed to the log file and the IDE's - /// console output as well. - llvm::Error ConfigureIO(std::FILE *overrideOut, std::FILE *overrideErr); - - /// Stop the redirected IO threads and associated pipes. - void StopIO(); - // Serialize the JSON value into a string and send the JSON packet to // the "out" stream. void SendJSON(const llvm::json::Value &json); diff --git a/lldb/tools/lldb-dap/IOStream.h b/lldb/tools/lldb-dap/IOStream.h index 74889eb2e5a86..57d5fd458b716 100644 --- a/lldb/tools/lldb-dap/IOStream.h +++ b/lldb/tools/lldb-dap/IOStream.h @@ -52,9 +52,6 @@ struct StreamDescriptor { struct InputStream { StreamDescriptor descriptor; - explicit InputStream(StreamDescriptor descriptor) - : descriptor(std::move(descriptor)) {} - bool read_full(std::ofstream *log, size_t length, std::string &text); bool read_line(std::ofstream *log, std::string &line); @@ -65,9 +62,6 @@ struct InputStream { struct OutputStream { StreamDescriptor descriptor; - explicit OutputStream(StreamDescriptor descriptor) - : descriptor(std::move(descriptor)) {} - bool write_full(llvm::StringRef str); }; } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/OutputRedirector.cpp b/lldb/tools/lldb-dap/OutputRedirector.cpp index 8fcbcfec99c44..2c2f49569869b 100644 --- a/lldb/tools/lldb-dap/OutputRedirector.cpp +++ b/lldb/tools/lldb-dap/OutputRedirector.cpp @@ -6,8 +6,6 @@ // //===----------------------------------------------------------------------===/ -#include "llvm/Support/Error.h" -#include #if defined(_WIN32) #include #include @@ -19,59 +17,47 @@ #include "OutputRedirector.h" #include "llvm/ADT/StringRef.h" -using lldb_private::Pipe; -using lldb_private::Status; -using llvm::createStringError; -using llvm::Error; -using llvm::Expected; -using llvm::StringRef; +using namespace llvm; namespace lldb_dap { -Expected OutputRedirector::GetWriteFileDescriptor() { - if (!m_pipe.CanWrite()) - return createStringError(std::errc::bad_file_descriptor, - "write handle is not open for writing"); - return m_pipe.GetWriteFileDescriptor(); -} +Error RedirectFd(int fd, std::function callback) { + int new_fd[2]; +#if defined(_WIN32) + if (_pipe(new_fd, 4096, O_TEXT) == -1) { +#else + if (pipe(new_fd) == -1) { +#endif + int error = errno; + return createStringError(inconvertibleErrorCode(), + "Couldn't create new pipe for fd %d. %s", fd, + strerror(error)); + } -Error OutputRedirector::RedirectTo(std::function callback) { - Status status = m_pipe.CreateNew(/*child_process_inherit=*/false); - if (status.Fail()) - return status.takeError(); + if (dup2(new_fd[1], fd) == -1) { + int error = errno; + return createStringError(inconvertibleErrorCode(), + "Couldn't override the fd %d. %s", fd, + strerror(error)); + } - m_forwarder = std::thread([this, callback]() { + int read_fd = new_fd[0]; + std::thread t([read_fd, callback]() { char buffer[OutputBufferSize]; - while (m_pipe.CanRead() && !m_stopped) { - size_t bytes_read; - Status status = m_pipe.Read(&buffer, sizeof(buffer), bytes_read); - if (status.Fail()) - continue; - - // EOF detected - if (bytes_read == 0 || m_stopped) + while (true) { + ssize_t bytes_count = read(read_fd, &buffer, sizeof(buffer)); + if (bytes_count == 0) + return; + if (bytes_count == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; break; - - callback(StringRef(buffer, bytes_read)); + } + callback(StringRef(buffer, bytes_count)); } }); - + t.detach(); return Error::success(); } -void OutputRedirector::Stop() { - m_stopped = true; - - if (m_pipe.CanWrite()) { - // Closing the pipe may not be sufficient to wake up the thread in case the - // write descriptor is duplicated (to stdout/err or to another process). - // Write a null byte to ensure the read call returns. - char buf[] = "\0"; - size_t bytes_written; - m_pipe.Write(buf, sizeof(buf), bytes_written); - m_pipe.CloseWriteFileDescriptor(); - m_forwarder.join(); - } -} - } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/OutputRedirector.h b/lldb/tools/lldb-dap/OutputRedirector.h index 41ea05c22c691..e26d1648b104f 100644 --- a/lldb/tools/lldb-dap/OutputRedirector.h +++ b/lldb/tools/lldb-dap/OutputRedirector.h @@ -9,39 +9,17 @@ #ifndef LLDB_TOOLS_LLDB_DAP_OUTPUT_REDIRECTOR_H #define LLDB_TOOLS_LLDB_DAP_OUTPUT_REDIRECTOR_H -#include "lldb/Host/Pipe.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" -#include -#include -#include namespace lldb_dap { -class OutputRedirector { -public: - /// Creates writable file descriptor that will invoke the given callback on - /// each write in a background thread. - /// - /// \return - /// \a Error::success if the redirection was set up correctly, or an error - /// otherwise. - llvm::Error RedirectTo(std::function callback); - - llvm::Expected GetWriteFileDescriptor(); - void Stop(); - - ~OutputRedirector() { Stop(); } - - OutputRedirector() = default; - OutputRedirector(const OutputRedirector &) = delete; - OutputRedirector &operator=(const OutputRedirector &) = delete; - -private: - std::atomic m_stopped = false; - lldb_private::Pipe m_pipe; - std::thread m_forwarder; -}; +/// Redirects the output of a given file descriptor to a callback. +/// +/// \return +/// \a Error::success if the redirection was set up correctly, or an error +/// otherwise. +llvm::Error RedirectFd(int fd, std::function callback); } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 6c524081c493e..7e8f7b5f6df67 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -10,10 +10,10 @@ #include "FifoFiles.h" #include "JSONUtils.h" #include "LLDBUtils.h" +#include "OutputRedirector.h" #include "RunInTerminal.h" #include "Watchpoint.h" #include "lldb/API/SBDeclaration.h" -#include "lldb/API/SBEvent.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBMemoryRegionInfo.h" @@ -41,11 +41,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -142,14 +140,15 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(std::ofstream *log, int portno) { +SOCKET AcceptConnection(DAP &dap, int portno) { // Accept a socket connection from any host on "portno". SOCKET newsockfd = -1; struct sockaddr_in serv_addr, cli_addr; SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { - if (log) - *log << "error: opening socket (" << strerror(errno) << ")" << std::endl; + if (dap.log) + *dap.log << "error: opening socket (" << strerror(errno) << ")" + << std::endl; } else { memset((char *)&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; @@ -157,9 +156,9 @@ SOCKET AcceptConnection(std::ofstream *log, int portno) { serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - if (log) - *log << "error: binding socket (" << strerror(errno) << ")" - << std::endl; + if (dap.log) + *dap.log << "error: binding socket (" << strerror(errno) << ")" + << std::endl; } else { listen(sockfd, 5); socklen_t clilen = sizeof(cli_addr); @@ -167,8 +166,8 @@ SOCKET AcceptConnection(std::ofstream *log, int portno) { llvm::sys::RetryAfterSignal(static_cast(-1), accept, sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd < 0) - if (log) - *log << "error: accept (" << strerror(errno) << ")" << std::endl; + if (dap.log) + *dap.log << "error: accept (" << strerror(errno) << ")" << std::endl; } #if defined(_WIN32) closesocket(sockfd); @@ -1103,7 +1102,6 @@ void request_disconnect(DAP &dap, const llvm::json::Object &request) { dap.broadcaster.BroadcastEventByType(eBroadcastBitStopProgressThread); dap.progress_event_thread.join(); } - dap.StopIO(); dap.disconnecting = true; } @@ -1873,36 +1871,7 @@ void request_initialize(DAP &dap, const llvm::json::Object &request) { // which may affect the outcome of tests. bool source_init_file = GetBoolean(arguments, "sourceInitFile", true); - // Do not source init files until in/out/err are configured. - dap.debugger = lldb::SBDebugger::Create(false); - dap.debugger.SetInputFile(dap.in); - auto out_fd = dap.out.GetWriteFileDescriptor(); - if (llvm::Error err = out_fd.takeError()) { - response["success"] = false; - EmplaceSafeString(response, "message", llvm::toString(std::move(err))); - dap.SendJSON(llvm::json::Value(std::move(response))); - return; - } - dap.debugger.SetOutputFile(lldb::SBFile(*out_fd, "w", false)); - auto err_fd = dap.err.GetWriteFileDescriptor(); - if (llvm::Error err = err_fd.takeError()) { - response["success"] = false; - EmplaceSafeString(response, "message", llvm::toString(std::move(err))); - dap.SendJSON(llvm::json::Value(std::move(response))); - return; - } - dap.debugger.SetErrorFile(lldb::SBFile(*err_fd, "w", false)); - - auto interp = dap.debugger.GetCommandInterpreter(); - - if (source_init_file) { - dap.debugger.SkipLLDBInitFiles(false); - dap.debugger.SkipAppInitFiles(false); - lldb::SBCommandReturnObject init; - interp.SourceInitFileInGlobalDirectory(init); - interp.SourceInitFileInHomeDirectory(init); - } - + dap.debugger = lldb::SBDebugger::Create(source_init_file); if (llvm::Error err = dap.RunPreInitCommands()) { response["success"] = false; EmplaceSafeString(response, "message", llvm::toString(std::move(err))); @@ -4941,14 +4910,36 @@ static void redirection_test() { fflush(stderr); } -/// Duplicates a file descriptor, setting FD_CLOEXEC if applicable. -static int DuplicateFileDescriptor(int fd) { -#if defined(F_DUPFD_CLOEXEC) - // Ensure FD_CLOEXEC is set. - return ::fcntl(fd, F_DUPFD_CLOEXEC, 0); -#else - return ::dup(fd); -#endif +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +static int SetupStdoutStderrRedirection(DAP &dap) { + int stdoutfd = fileno(stdout); + int new_stdout_fd = dup(stdoutfd); + auto output_callback_stderr = [&dap](llvm::StringRef data) { + dap.SendOutput(OutputType::Stderr, data); + }; + auto output_callback_stdout = [&dap](llvm::StringRef data) { + dap.SendOutput(OutputType::Stdout, data); + }; + if (llvm::Error err = RedirectFd(stdoutfd, output_callback_stdout)) { + std::string error_message = llvm::toString(std::move(err)); + if (dap.log) + *dap.log << error_message << std::endl; + output_callback_stderr(error_message); + } + if (llvm::Error err = RedirectFd(fileno(stderr), output_callback_stderr)) { + std::string error_message = llvm::toString(std::move(err)); + if (dap.log) + *dap.log << error_message << std::endl; + output_callback_stderr(error_message); + } + + return new_stdout_fd; } int main(int argc, char *argv[]) { @@ -5039,88 +5030,47 @@ int main(int argc, char *argv[]) { } #endif - std::unique_ptr log = nullptr; - const char *log_file_path = getenv("LLDBDAP_LOG"); - if (log_file_path) - log = std::make_unique(log_file_path); - // Initialize LLDB first before we do anything. - lldb::SBError error = lldb::SBDebugger::InitializeWithErrorHandling(); - if (error.Fail()) { - lldb::SBStream os; - error.GetDescription(os); - llvm::errs() << "lldb initialize failed: " << os.GetData() << "\n"; - return EXIT_FAILURE; - } + lldb::SBDebugger::Initialize(); // Terminate the debugger before the C++ destructor chain kicks in. auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { - printf("Listening on port %i...\n", portno); - SOCKET socket_fd = AcceptConnection(log.get(), portno); - if (socket_fd < 0) - return EXIT_FAILURE; + DAP dap = DAP(program_path.str(), default_repl_mode); - input = StreamDescriptor::from_socket(socket_fd, true); - output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) - // Windows opens stdout and stdin in text mode which converts \n to 13,10 - // while the value is just 10 on Darwin/Linux. Setting the file mode to - // binary fixes this. - int result = _setmode(fileno(stdout), _O_BINARY); - assert(result); - result = _setmode(fileno(stdin), _O_BINARY); - UNUSED_IF_ASSERT_DISABLED(result); - assert(result); -#endif + RegisterRequestCallbacks(dap); - int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); - if (stdout_fd == -1) { - llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + // stdout/stderr redirection to the IDE's console + int new_stdout_fd = SetupStdoutStderrRedirection(dap); + + if (portno != -1) { + printf("Listening on port %i...\n", portno); + SOCKET socket_fd = AcceptConnection(dap, portno); + if (socket_fd >= 0) { + dap.input.descriptor = StreamDescriptor::from_socket(socket_fd, true); + dap.output.descriptor = StreamDescriptor::from_socket(socket_fd, false); + } else { return EXIT_FAILURE; } + } else { + dap.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false); + dap.output.descriptor = StreamDescriptor::from_file(new_stdout_fd, false); - redirectOut = stdout; - redirectErr = stderr; - - input = StreamDescriptor::from_file(fileno(stdin), false); - output = StreamDescriptor::from_file(stdout_fd, false); - } - - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, - std::move(input), std::move(output)); - - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), - "Failed to configure lldb-dap IO operations: "); - return EXIT_FAILURE; + /// used only by TestVSCode_redirection_to_console.py + if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); } - RegisterRequestCallbacks(dap); - for (const std::string &arg : input_args.getAllArgValues(OPT_pre_init_command)) { dap.pre_init_commands.push_back(arg); } - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) - redirection_test(); - bool CleanExit = true; if (auto Err = dap.Loop()) { - if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + if (dap.log) + *dap.log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; CleanExit = false; } From b66f6b25cb5107d4c8f78d13b08d2bdba39ad919 Mon Sep 17 00:00:00 2001 From: Chris B Date: Wed, 8 Jan 2025 08:55:02 -0600 Subject: [PATCH 024/163] Revert #116331 & #121852 (#122105) --- clang/include/clang/Basic/Attr.td | 10 -- clang/lib/CodeGen/CGStmt.cpp | 6 -- clang/lib/CodeGen/CodeGenFunction.cpp | 25 +---- clang/lib/CodeGen/CodeGenFunction.h | 4 - clang/lib/Sema/SemaStmtAttr.cpp | 8 -- clang/test/AST/HLSL/HLSLControlFlowHint.hlsl | 43 -------- .../test/CodeGenHLSL/HLSLControlFlowHint.hlsl | 48 --------- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +- .../Target/DirectX/DXILTranslateMetadata.cpp | 37 ------- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 29 ++---- llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 44 +++------ .../CodeGen/DirectX/HLSLControlFlowHint.ll | 98 ------------------- .../HLSLControlFlowHint-pass-check.ll | 90 ----------------- .../SPIRV/structurizer/HLSLControlFlowHint.ll | 91 ----------------- 14 files changed, 19 insertions(+), 516 deletions(-) delete mode 100644 clang/test/AST/HLSL/HLSLControlFlowHint.hlsl delete mode 100644 clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl delete mode 100644 llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll delete mode 100644 llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint-pass-check.ll delete mode 100644 llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6d7f65ab2c613..12faf06597008 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4335,16 +4335,6 @@ def HLSLLoopHint: StmtAttr { let Documentation = [HLSLLoopHintDocs, HLSLUnrollHintDocs]; } -def HLSLControlFlowHint: StmtAttr { - /// [branch] - /// [flatten] - let Spellings = [Microsoft<"branch">, Microsoft<"flatten">]; - let Subjects = SubjectList<[IfStmt], - ErrorDiag, "'if' statements">; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; -} - def CapturedRecord : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index c8ff48fc73312..a87c50b8a1cbb 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -757,8 +757,6 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { bool noinline = false; bool alwaysinline = false; bool noconvergent = false; - HLSLControlFlowHintAttr::Spelling flattenOrBranch = - HLSLControlFlowHintAttr::SpellingNotCalculated; const CallExpr *musttail = nullptr; for (const auto *A : S.getAttrs()) { @@ -790,9 +788,6 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { Builder.CreateAssumption(AssumptionVal); } } break; - case attr::HLSLControlFlowHint: { - flattenOrBranch = cast(A)->getSemanticSpelling(); - } break; } } SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge); @@ -800,7 +795,6 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline); SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt, noconvergent); SaveAndRestore save_musttail(MustTailCall, musttail); - SaveAndRestore save_flattenOrBranch(HLSLControlFlowAttr, flattenOrBranch); EmitStmt(S.getSubStmt(), S.getAttrs()); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 067ff55b87ae6..af58fa64f8658 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -40,7 +40,6 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/FPEnv.h" -#include "llvm/IR/Instruction.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" @@ -2084,29 +2083,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr( Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount); } - llvm::Instruction *BrInst = Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, - Weights, Unpredictable); - switch (HLSLControlFlowAttr) { - case HLSLControlFlowHintAttr::Microsoft_branch: - case HLSLControlFlowHintAttr::Microsoft_flatten: { - llvm::MDBuilder MDHelper(CGM.getLLVMContext()); - - llvm::ConstantInt *BranchHintConstant = - HLSLControlFlowAttr == - HLSLControlFlowHintAttr::Spelling::Microsoft_branch - ? llvm::ConstantInt::get(CGM.Int32Ty, 1) - : llvm::ConstantInt::get(CGM.Int32Ty, 2); - - SmallVector Vals( - {MDHelper.createString("hlsl.controlflow.hint"), - MDHelper.createConstant(BranchHintConstant)}); - BrInst->setMetadata("hlsl.controlflow.hint", - llvm::MDNode::get(CGM.getLLVMContext(), Vals)); - break; - } - case HLSLControlFlowHintAttr::SpellingNotCalculated: - break; - } + Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable); } /// ErrorUnsupported - Print out an error that codegen doesn't support the diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index bc612a0bfb32b..f2240f8308ce3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -615,10 +615,6 @@ class CodeGenFunction : public CodeGenTypeCache { /// True if the current statement has noconvergent attribute. bool InNoConvergentAttributedStmt = false; - /// HLSL Branch attribute. - HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr = - HLSLControlFlowHintAttr::SpellingNotCalculated; - // The CallExpr within the current statement that the musttail attribute // applies to. nullptr if there is no 'musttail' on the current statement. const CallExpr *MustTailCall = nullptr; diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 422d8abc1028a..106e2430de901 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -619,12 +619,6 @@ static Attr *handleHLSLLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, return ::new (S.Context) HLSLLoopHintAttr(S.Context, A, UnrollFactor); } -static Attr *handleHLSLControlFlowHint(Sema &S, Stmt *St, const ParsedAttr &A, - SourceRange Range) { - - return ::new (S.Context) HLSLControlFlowHintAttr(S.Context, A); -} - static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { if (A.isInvalid() || A.getKind() == ParsedAttr::IgnoredAttribute) @@ -661,8 +655,6 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleLoopHintAttr(S, St, A, Range); case ParsedAttr::AT_HLSLLoopHint: return handleHLSLLoopHintAttr(S, St, A, Range); - case ParsedAttr::AT_HLSLControlFlowHint: - return handleHLSLControlFlowHint(S, St, A, Range); case ParsedAttr::AT_OpenCLUnrollHint: return handleOpenCLUnrollHint(S, St, A, Range); case ParsedAttr::AT_Suppress: diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl deleted file mode 100644 index a36779c05fbc9..0000000000000 --- a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -ast-dump %s | FileCheck %s - -// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used branch 'int (int)' -// CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} < -// CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> branch -export int branch(int X){ - int resp; - [branch] if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} - -// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used flatten 'int (int)' -// CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} < -// CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> flatten -export int flatten(int X){ - int resp; - [flatten] if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} - -// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used no_attr 'int (int)' -// CHECK-NOT: AttributedStmt 0x{{[0-9A-Fa-f]+}} < -// CHECK-NOT: -HLSLControlFlowHintAttr -export int no_attr(int X){ - int resp; - if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} diff --git a/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl b/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl deleted file mode 100644 index aa13b27581850..0000000000000 --- a/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl +++ /dev/null @@ -1,48 +0,0 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s - -// CHECK: define {{.*}} i32 {{.*}}test_branch{{.*}}(i32 {{.*}} [[VALD:%.*]]) -// CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4 -// CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0 -// CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_BRANCH:![0-9]+]] -export int test_branch(int X){ - int resp; - [branch] if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} - -// CHECK: define {{.*}} i32 {{.*}}test_flatten{{.*}}(i32 {{.*}} [[VALD:%.*]]) -// CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4 -// CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0 -// CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_FLATTEN:![0-9]+]] -export int test_flatten(int X){ - int resp; - [flatten] if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} - -// CHECK: define {{.*}} i32 {{.*}}test_no_attr{{.*}}(i32 {{.*}} [[VALD:%.*]]) -// CHECK-NOT: !hlsl.controlflow.hint -export int test_no_attr(int X){ - int resp; - if (X > 0) { - resp = -X; - } else { - resp = X * 2; - } - - return resp; -} - -//CHECK: [[HINT_BRANCH]] = !{!"hlsl.controlflow.hint", i32 1} -//CHECK: [[HINT_FLATTEN]] = !{!"hlsl.controlflow.hint", i32 2} diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index e6e21dcd6d699..c72179e3e18a3 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -33,7 +33,7 @@ let TargetPrefix = "spv" in { def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg>]>; def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>; def int_spv_loop_merge : Intrinsic<[], [llvm_vararg_ty]>; - def int_spv_selection_merge : Intrinsic<[], [llvm_any_ty, llvm_i32_ty], [ImmArg>]>; + def int_spv_selection_merge : Intrinsic<[], [llvm_vararg_ty]>; def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>; def int_spv_unreachable : Intrinsic<[], []>; def int_spv_alloca : Intrinsic<[llvm_any_ty], [llvm_i8_ty], [ImmArg>]>; diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index ad079f45c8829..5afe6b2d2883d 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -15,14 +15,12 @@ #include "llvm/ADT/Twine.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" -#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" @@ -302,39 +300,6 @@ static MDTuple *emitTopLevelLibraryNode(Module &M, MDNode *RMD, return constructEntryMetadata(nullptr, nullptr, RMD, Properties, Ctx); } -// TODO: We might need to refactor this to be more generic, -// in case we need more metadata to be replaced. -static void translateBranchMetadata(Module &M) { - for (Function &F : M) { - for (BasicBlock &BB : F) { - Instruction *BBTerminatorInst = BB.getTerminator(); - - MDNode *HlslControlFlowMD = - BBTerminatorInst->getMetadata("hlsl.controlflow.hint"); - - if (!HlslControlFlowMD) - continue; - - assert(HlslControlFlowMD->getNumOperands() == 2 && - "invalid operands for hlsl.controlflow.hint"); - - MDBuilder MDHelper(M.getContext()); - ConstantInt *Op1 = - mdconst::extract(HlslControlFlowMD->getOperand(1)); - - SmallVector Vals( - ArrayRef{MDHelper.createString("dx.controlflow.hints"), - MDHelper.createConstant(Op1)}); - - MDNode *MDNode = llvm::MDNode::get(M.getContext(), Vals); - - BBTerminatorInst->setMetadata("dx.controlflow.hints", MDNode); - BBTerminatorInst->setMetadata("hlsl.controlflow.hint", nullptr); - } - F.clearMetadata(); - } -} - static void translateMetadata(Module &M, DXILBindingMap &DBM, DXILResourceTypeMap &DRTM, const Resources &MDResources, @@ -407,7 +372,6 @@ PreservedAnalyses DXILTranslateMetadata::run(Module &M, const dxil::ModuleMetadataInfo MMDI = MAM.getResult(M); translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI); - translateBranchMetadata(M); return PreservedAnalyses::all(); } @@ -445,7 +409,6 @@ class DXILTranslateMetadataLegacy : public ModulePass { getAnalysis().getModuleMetadata(); translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI); - translateBranchMetadata(M); return true; } }; diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 237f71a1b70e5..28c9b81db51f5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -33,7 +33,6 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" #define DEBUG_TYPE "spirv-isel" @@ -46,17 +45,6 @@ using ExtInstList = namespace { -llvm::SPIRV::SelectionControl::SelectionControl -getSelectionOperandForImm(int Imm) { - if (Imm == 2) - return SPIRV::SelectionControl::Flatten; - if (Imm == 1) - return SPIRV::SelectionControl::DontFlatten; - if (Imm == 0) - return SPIRV::SelectionControl::None; - llvm_unreachable("Invalid immediate"); -} - #define GET_GLOBALISEL_PREDICATE_BITSET #include "SPIRVGenGlobalISel.inc" #undef GET_GLOBALISEL_PREDICATE_BITSET @@ -2830,8 +2818,12 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, } return MIB.constrainAllUses(TII, TRI, RBI); } - case Intrinsic::spv_loop_merge: { - auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLoopMerge)); + case Intrinsic::spv_loop_merge: + case Intrinsic::spv_selection_merge: { + const auto Opcode = IID == Intrinsic::spv_selection_merge + ? SPIRV::OpSelectionMerge + : SPIRV::OpLoopMerge; + auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)); for (unsigned i = 1; i < I.getNumExplicitOperands(); ++i) { assert(I.getOperand(i).isMBB()); MIB.addMBB(I.getOperand(i).getMBB()); @@ -2839,15 +2831,6 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, MIB.addImm(SPIRV::SelectionControl::None); return MIB.constrainAllUses(TII, TRI, RBI); } - case Intrinsic::spv_selection_merge: { - auto MIB = - BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSelectionMerge)); - assert(I.getOperand(1).isMBB() && - "operand 1 to spv_selection_merge must be a basic block"); - MIB.addMBB(I.getOperand(1).getMBB()); - MIB.addImm(getSelectionOperandForImm(I.getOperand(2).getImm())); - return MIB.constrainAllUses(TII, TRI, RBI); - } case Intrinsic::spv_cmpxchg: return selectAtomicCmpXchg(ResVReg, ResType, I); case Intrinsic::spv_unreachable: diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp index 2e4343c7922f1..336cde4e78224 100644 --- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp @@ -18,16 +18,14 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/IR/Analysis.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsSPIRV.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/InitializePasses.h" -#include "llvm/PassRegistry.h" -#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/LoopSimplify.h" #include "llvm/Transforms/Utils/LowerMemIntrinsics.h" @@ -648,7 +646,8 @@ class SPIRVStructurizer : public FunctionPass { Builder.SetInsertPoint(Header->getTerminator()); auto MergeAddress = BlockAddress::get(BB.getParent(), &BB); - createOpSelectMerge(&Builder, MergeAddress); + SmallVector Args = {MergeAddress}; + Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args}); Modified = true; } @@ -770,9 +769,10 @@ class SPIRVStructurizer : public FunctionPass { BasicBlock *Merge = Candidates[0]; auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge); + SmallVector Args = {MergeAddress}; IRBuilder<> Builder(&BB); Builder.SetInsertPoint(BB.getTerminator()); - createOpSelectMerge(&Builder, MergeAddress); + Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args}); } return Modified; @@ -1105,7 +1105,8 @@ class SPIRVStructurizer : public FunctionPass { Builder.SetInsertPoint(Header->getTerminator()); auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge); - createOpSelectMerge(&Builder, MergeAddress); + SmallVector Args = {MergeAddress}; + Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args}); continue; } @@ -1119,7 +1120,8 @@ class SPIRVStructurizer : public FunctionPass { Builder.SetInsertPoint(Header->getTerminator()); auto MergeAddress = BlockAddress::get(NewMerge->getParent(), NewMerge); - createOpSelectMerge(&Builder, MergeAddress); + SmallVector Args = {MergeAddress}; + Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args}); } return Modified; @@ -1206,27 +1208,6 @@ class SPIRVStructurizer : public FunctionPass { AU.addPreserved(); FunctionPass::getAnalysisUsage(AU); } - - void createOpSelectMerge(IRBuilder<> *Builder, BlockAddress *MergeAddress) { - Instruction *BBTerminatorInst = Builder->GetInsertBlock()->getTerminator(); - - MDNode *MDNode = BBTerminatorInst->getMetadata("hlsl.controlflow.hint"); - - ConstantInt *BranchHint = llvm::ConstantInt::get(Builder->getInt32Ty(), 0); - - if (MDNode) { - assert(MDNode->getNumOperands() == 2 && - "invalid metadata hlsl.controlflow.hint"); - BranchHint = mdconst::extract(MDNode->getOperand(1)); - - assert(BranchHint && "invalid metadata value for hlsl.controlflow.hint"); - } - - llvm::SmallVector Args = {MergeAddress, BranchHint}; - - Builder->CreateIntrinsic(Intrinsic::spv_selection_merge, - {MergeAddress->getType()}, {Args}); - } }; } // namespace llvm @@ -1248,11 +1229,8 @@ FunctionPass *llvm::createSPIRVStructurizerPass() { PreservedAnalyses SPIRVStructurizerWrapper::run(Function &F, FunctionAnalysisManager &AF) { - - auto FPM = legacy::FunctionPassManager(F.getParent()); - FPM.add(createSPIRVStructurizerPass()); - - if (!FPM.run(F)) + FunctionPass *StructurizerPass = createSPIRVStructurizerPass(); + if (!StructurizerPass->runOnFunction(F)) return PreservedAnalyses::all(); PreservedAnalyses PA; PA.preserveSet(); diff --git a/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll b/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll deleted file mode 100644 index fe66e481359bb..0000000000000 --- a/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll +++ /dev/null @@ -1,98 +0,0 @@ -; RUN: opt -S -dxil-op-lower -dxil-translate-metadata -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s - -; This test make sure LLVM metadata is being translated into DXIL. - - -; CHECK: define i32 @test_branch(i32 %X) -; CHECK-NO: hlsl.controlflow.hint -; CHECK: br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints [[HINT_BRANCH:![0-9]+]] -define i32 @test_branch(i32 %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !0 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - - -; CHECK: define i32 @test_flatten(i32 %X) -; CHECK-NO: hlsl.controlflow.hint -; CHECK: br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints [[HINT_FLATTEN:![0-9]+]] -define i32 @test_flatten(i32 %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !1 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - - -; CHECK: define i32 @test_no_attr(i32 %X) -; CHECK-NO: hlsl.controlflow.hint -; CHECK-NO: !dx.controlflow.hints -define i32 @test_no_attr(i32 %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} -; CHECK-NO: hlsl.controlflow.hint -; CHECK: [[HINT_BRANCH]] = !{!"dx.controlflow.hints", i32 1} -; CHECK: [[HINT_FLATTEN]] = !{!"dx.controlflow.hints", i32 2} -!0 = !{!"hlsl.controlflow.hint", i32 1} -!1 = !{!"hlsl.controlflow.hint", i32 2} diff --git a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint-pass-check.ll b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint-pass-check.ll deleted file mode 100644 index 9911b3119ce52..0000000000000 --- a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint-pass-check.ll +++ /dev/null @@ -1,90 +0,0 @@ -; RUN: opt -passes='spirv-structurizer' -S -mtriple=spirv-unknown-unknown %s | FileCheck %s - -; CHECK-LABEL: define spir_func noundef i32 @test_branch -; CHECK: call void @llvm.spv.selection.merge.p0(ptr blockaddress(@test_branch, %if.end), i32 1) -; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !{{[0-9]+}} -define spir_func noundef i32 @test_branch(i32 noundef %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !0 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - -; CHECK-LABEL: define spir_func noundef i32 @test_flatten -; CHECK: call void @llvm.spv.selection.merge.p0(ptr blockaddress(@test_flatten, %if.end), i32 2) -; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !{{[0-9]+}} -define spir_func noundef i32 @test_flatten(i32 noundef %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !1 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} -; CHECK-LABEL: define spir_func noundef i32 @test_no_attr -; CHECK: call void @llvm.spv.selection.merge.p0(ptr blockaddress(@test_no_attr, %if.end), i32 0) -; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.else -define spir_func noundef i32 @test_no_attr(i32 noundef %X) { -entry: - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - -!0 = !{!"hlsl.controlflow.hint", i32 1} -!1 = !{!"hlsl.controlflow.hint", i32 2} diff --git a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll deleted file mode 100644 index 848eaf70f5a19..0000000000000 --- a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll +++ /dev/null @@ -1,91 +0,0 @@ -; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} - - -define spir_func noundef i32 @test_branch(i32 noundef %X) { -entry: -; CHECK-LABEL: ; -- Begin function test_branch -; OpSelectionMerge %[[#]] DontFlatten - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !0 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - - -define spir_func noundef i32 @test_flatten(i32 noundef %X) { -entry: -; CHECK-LABEL: ; -- Begin function test_flatten -; OpSelectionMerge %[[#]] Flatten - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !1 - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - -define spir_func noundef i32 @test_no_attr(i32 noundef %X) { -entry: -; CHECK-LABEL: ; -- Begin function test_no_attr -; OpSelectionMerge %[[#]] None - %X.addr = alloca i32, align 4 - %resp = alloca i32, align 4 - store i32 %X, ptr %X.addr, align 4 - %0 = load i32, ptr %X.addr, align 4 - %cmp = icmp sgt i32 %0, 0 - br i1 %cmp, label %if.then, label %if.else - -if.then: ; preds = %entry - %1 = load i32, ptr %X.addr, align 4 - %sub = sub nsw i32 0, %1 - store i32 %sub, ptr %resp, align 4 - br label %if.end - -if.else: ; preds = %entry - %2 = load i32, ptr %X.addr, align 4 - %mul = mul nsw i32 %2, 2 - store i32 %mul, ptr %resp, align 4 - br label %if.end - -if.end: ; preds = %if.else, %if.then - %3 = load i32, ptr %resp, align 4 - ret i32 %3 -} - -!0 = !{!"hlsl.controlflow.hint", i32 1} -!1 = !{!"hlsl.controlflow.hint", i32 2} From f37bee1d929a90dd3dbb67a4a9d0a52400a8a78f Mon Sep 17 00:00:00 2001 From: Mikhail Gudim Date: Wed, 8 Jan 2025 10:00:41 -0500 Subject: [PATCH 025/163] [ReachingDefAnalysis][NFC] Rename `PhysReg` to `Reg`. (#122112) This is in order to prepare for future MR where we will extend `ReachingDefAnalysis` to stack slots. --- .../llvm/CodeGen/ReachingDefAnalysis.h | 55 ++++--- llvm/lib/CodeGen/ReachingDefAnalysis.cpp | 144 +++++++++--------- 2 files changed, 96 insertions(+), 103 deletions(-) diff --git a/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h index d6a1f064ec0a5..0c1e707e4ecbb 100644 --- a/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h +++ b/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h @@ -176,26 +176,25 @@ class ReachingDefAnalysis : public MachineFunctionPass { void traverse(); /// Provides the instruction id of the closest reaching def instruction of - /// PhysReg that reaches MI, relative to the begining of MI's basic block. - int getReachingDef(MachineInstr *MI, MCRegister PhysReg) const; + /// Reg that reaches MI, relative to the begining of MI's basic block. + int getReachingDef(MachineInstr *MI, MCRegister Reg) const; - /// Return whether A and B use the same def of PhysReg. + /// Return whether A and B use the same def of Reg. bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, - MCRegister PhysReg) const; + MCRegister Reg) const; /// Return whether the reaching def for MI also is live out of its parent /// block. - bool isReachingDefLiveOut(MachineInstr *MI, MCRegister PhysReg) const; + bool isReachingDefLiveOut(MachineInstr *MI, MCRegister Reg) const; - /// Return the local MI that produces the live out value for PhysReg, or + /// Return the local MI that produces the live out value for Reg, or /// nullptr for a non-live out or non-local def. MachineInstr *getLocalLiveOutMIDef(MachineBasicBlock *MBB, - MCRegister PhysReg) const; + MCRegister Reg) const; /// If a single MachineInstr creates the reaching definition, then return it. /// Otherwise return null. - MachineInstr *getUniqueReachingMIDef(MachineInstr *MI, - MCRegister PhysReg) const; + MachineInstr *getUniqueReachingMIDef(MachineInstr *MI, MCRegister Reg) const; /// If a single MachineInstr creates the reaching definition, for MIs operand /// at Idx, then return it. Otherwise return null. @@ -207,44 +206,43 @@ class ReachingDefAnalysis : public MachineFunctionPass { /// Provide whether the register has been defined in the same basic block as, /// and before, MI. - bool hasLocalDefBefore(MachineInstr *MI, MCRegister PhysReg) const; + bool hasLocalDefBefore(MachineInstr *MI, MCRegister Reg) const; /// Return whether the given register is used after MI, whether it's a local /// use or a live out. - bool isRegUsedAfter(MachineInstr *MI, MCRegister PhysReg) const; + bool isRegUsedAfter(MachineInstr *MI, MCRegister Reg) const; /// Return whether the given register is defined after MI. - bool isRegDefinedAfter(MachineInstr *MI, MCRegister PhysReg) const; + bool isRegDefinedAfter(MachineInstr *MI, MCRegister Reg) const; /// Provides the clearance - the number of instructions since the closest - /// reaching def instuction of PhysReg that reaches MI. - int getClearance(MachineInstr *MI, MCRegister PhysReg) const; + /// reaching def instuction of Reg that reaches MI. + int getClearance(MachineInstr *MI, MCRegister Reg) const; /// Provides the uses, in the same block as MI, of register that MI defines. /// This does not consider live-outs. - void getReachingLocalUses(MachineInstr *MI, MCRegister PhysReg, + void getReachingLocalUses(MachineInstr *MI, MCRegister Reg, InstSet &Uses) const; - /// Search MBB for a definition of PhysReg and insert it into Defs. If no + /// Search MBB for a definition of Reg and insert it into Defs. If no /// definition is found, recursively search the predecessor blocks for them. - void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, InstSet &Defs, + void getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg, InstSet &Defs, BlockSet &VisitedBBs) const; - void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, - InstSet &Defs) const; + void getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg, InstSet &Defs) const; /// For the given block, collect the instructions that use the live-in /// value of the provided register. Return whether the value is still /// live on exit. - bool getLiveInUses(MachineBasicBlock *MBB, MCRegister PhysReg, + bool getLiveInUses(MachineBasicBlock *MBB, MCRegister Reg, InstSet &Uses) const; - /// Collect the users of the value stored in PhysReg, which is defined + /// Collect the users of the value stored in Reg, which is defined /// by MI. - void getGlobalUses(MachineInstr *MI, MCRegister PhysReg, InstSet &Uses) const; + void getGlobalUses(MachineInstr *MI, MCRegister Reg, InstSet &Uses) const; - /// Collect all possible definitions of the value stored in PhysReg, which is + /// Collect all possible definitions of the value stored in Reg, which is /// used by MI. - void getGlobalReachingDefs(MachineInstr *MI, MCRegister PhysReg, + void getGlobalReachingDefs(MachineInstr *MI, MCRegister Reg, InstSet &Defs) const; /// Return whether From can be moved forwards to just before To. @@ -269,12 +267,12 @@ class ReachingDefAnalysis : public MachineFunctionPass { /// Return whether a MachineInstr could be inserted at MI and safely define /// the given register without affecting the program. - bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg) const; + bool isSafeToDefRegAt(MachineInstr *MI, MCRegister Reg) const; /// Return whether a MachineInstr could be inserted at MI and safely define /// the given register without affecting the program, ignoring any effects /// on the provided instructions. - bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg, + bool isSafeToDefRegAt(MachineInstr *MI, MCRegister Reg, InstSet &Ignore) const; private: @@ -309,9 +307,8 @@ class ReachingDefAnalysis : public MachineFunctionPass { MachineInstr *getInstFromId(MachineBasicBlock *MBB, int InstId) const; /// Provides the instruction of the closest reaching def instruction of - /// PhysReg that reaches MI, relative to the begining of MI's basic block. - MachineInstr *getReachingLocalMIDef(MachineInstr *MI, - MCRegister PhysReg) const; + /// Reg that reaches MI, relative to the begining of MI's basic block. + MachineInstr *getReachingLocalMIDef(MachineInstr *MI, MCRegister Reg) const; }; } // namespace llvm diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp index 79b0fa672cc69..3ab6315f9c8ee 100644 --- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp +++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp @@ -30,22 +30,22 @@ static bool isValidRegUse(const MachineOperand &MO) { return isValidReg(MO) && MO.isUse(); } -static bool isValidRegUseOf(const MachineOperand &MO, MCRegister PhysReg, +static bool isValidRegUseOf(const MachineOperand &MO, MCRegister Reg, const TargetRegisterInfo *TRI) { if (!isValidRegUse(MO)) return false; - return TRI->regsOverlap(MO.getReg(), PhysReg); + return TRI->regsOverlap(MO.getReg(), Reg); } static bool isValidRegDef(const MachineOperand &MO) { return isValidReg(MO) && MO.isDef(); } -static bool isValidRegDefOf(const MachineOperand &MO, MCRegister PhysReg, +static bool isValidRegDefOf(const MachineOperand &MO, MCRegister Reg, const TargetRegisterInfo *TRI) { if (!isValidRegDef(MO)) return false; - return TRI->regsOverlap(MO.getReg(), PhysReg); + return TRI->regsOverlap(MO.getReg(), Reg); } void ReachingDefAnalysis::enterBasicBlock(MachineBasicBlock *MBB) { @@ -261,7 +261,7 @@ void ReachingDefAnalysis::traverse() { } int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { assert(InstIds.count(MI) && "Unexpected machine instuction."); int InstId = InstIds.lookup(MI); int DefRes = ReachingDefDefaultVal; @@ -269,7 +269,7 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, assert(MBBNumber < MBBReachingDefs.numBlockIDs() && "Unexpected basic block number."); int LatestDef = ReachingDefDefaultVal; - for (MCRegUnit Unit : TRI->regunits(PhysReg)) { + for (MCRegUnit Unit : TRI->regunits(Reg)) { for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) { if (Def >= InstId) break; @@ -280,22 +280,21 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, return LatestDef; } -MachineInstr * -ReachingDefAnalysis::getReachingLocalMIDef(MachineInstr *MI, - MCRegister PhysReg) const { - return hasLocalDefBefore(MI, PhysReg) - ? getInstFromId(MI->getParent(), getReachingDef(MI, PhysReg)) - : nullptr; +MachineInstr *ReachingDefAnalysis::getReachingLocalMIDef(MachineInstr *MI, + MCRegister Reg) const { + return hasLocalDefBefore(MI, Reg) + ? getInstFromId(MI->getParent(), getReachingDef(MI, Reg)) + : nullptr; } bool ReachingDefAnalysis::hasSameReachingDef(MachineInstr *A, MachineInstr *B, - MCRegister PhysReg) const { + MCRegister Reg) const { MachineBasicBlock *ParentA = A->getParent(); MachineBasicBlock *ParentB = B->getParent(); if (ParentA != ParentB) return false; - return getReachingDef(A, PhysReg) == getReachingDef(B, PhysReg); + return getReachingDef(A, Reg) == getReachingDef(B, Reg); } MachineInstr *ReachingDefAnalysis::getInstFromId(MachineBasicBlock *MBB, @@ -318,19 +317,18 @@ MachineInstr *ReachingDefAnalysis::getInstFromId(MachineBasicBlock *MBB, return nullptr; } -int ReachingDefAnalysis::getClearance(MachineInstr *MI, - MCRegister PhysReg) const { +int ReachingDefAnalysis::getClearance(MachineInstr *MI, MCRegister Reg) const { assert(InstIds.count(MI) && "Unexpected machine instuction."); - return InstIds.lookup(MI) - getReachingDef(MI, PhysReg); + return InstIds.lookup(MI) - getReachingDef(MI, Reg); } bool ReachingDefAnalysis::hasLocalDefBefore(MachineInstr *MI, - MCRegister PhysReg) const { - return getReachingDef(MI, PhysReg) >= 0; + MCRegister Reg) const { + return getReachingDef(MI, Reg) >= 0; } void ReachingDefAnalysis::getReachingLocalUses(MachineInstr *Def, - MCRegister PhysReg, + MCRegister Reg, InstSet &Uses) const { MachineBasicBlock *MBB = Def->getParent(); MachineBasicBlock::iterator MI = MachineBasicBlock::iterator(Def); @@ -340,11 +338,11 @@ void ReachingDefAnalysis::getReachingLocalUses(MachineInstr *Def, // If/when we find a new reaching def, we know that there's no more uses // of 'Def'. - if (getReachingLocalMIDef(&*MI, PhysReg) != Def) + if (getReachingLocalMIDef(&*MI, Reg) != Def) return; for (auto &MO : MI->operands()) { - if (!isValidRegUseOf(MO, PhysReg, TRI)) + if (!isValidRegUseOf(MO, Reg, TRI)) continue; Uses.insert(&*MI); @@ -354,15 +352,14 @@ void ReachingDefAnalysis::getReachingLocalUses(MachineInstr *Def, } } -bool ReachingDefAnalysis::getLiveInUses(MachineBasicBlock *MBB, - MCRegister PhysReg, +bool ReachingDefAnalysis::getLiveInUses(MachineBasicBlock *MBB, MCRegister Reg, InstSet &Uses) const { for (MachineInstr &MI : instructionsWithoutDebug(MBB->instr_begin(), MBB->instr_end())) { for (auto &MO : MI.operands()) { - if (!isValidRegUseOf(MO, PhysReg, TRI)) + if (!isValidRegUseOf(MO, Reg, TRI)) continue; - if (getReachingDef(&MI, PhysReg) >= 0) + if (getReachingDef(&MI, Reg) >= 0) return false; Uses.insert(&MI); } @@ -370,18 +367,18 @@ bool ReachingDefAnalysis::getLiveInUses(MachineBasicBlock *MBB, auto Last = MBB->getLastNonDebugInstr(); if (Last == MBB->end()) return true; - return isReachingDefLiveOut(&*Last, PhysReg); + return isReachingDefLiveOut(&*Last, Reg); } -void ReachingDefAnalysis::getGlobalUses(MachineInstr *MI, MCRegister PhysReg, +void ReachingDefAnalysis::getGlobalUses(MachineInstr *MI, MCRegister Reg, InstSet &Uses) const { MachineBasicBlock *MBB = MI->getParent(); // Collect the uses that each def touches within the block. - getReachingLocalUses(MI, PhysReg, Uses); + getReachingLocalUses(MI, Reg, Uses); // Handle live-out values. - if (auto *LiveOut = getLocalLiveOutMIDef(MI->getParent(), PhysReg)) { + if (auto *LiveOut = getLocalLiveOutMIDef(MI->getParent(), Reg)) { if (LiveOut != MI) return; @@ -389,9 +386,9 @@ void ReachingDefAnalysis::getGlobalUses(MachineInstr *MI, MCRegister PhysReg, SmallPtrSetVisited; while (!ToVisit.empty()) { MachineBasicBlock *MBB = ToVisit.pop_back_val(); - if (Visited.count(MBB) || !MBB->isLiveIn(PhysReg)) + if (Visited.count(MBB) || !MBB->isLiveIn(Reg)) continue; - if (getLiveInUses(MBB, PhysReg, Uses)) + if (getLiveInUses(MBB, Reg, Uses)) llvm::append_range(ToVisit, MBB->successors()); Visited.insert(MBB); } @@ -399,25 +396,25 @@ void ReachingDefAnalysis::getGlobalUses(MachineInstr *MI, MCRegister PhysReg, } void ReachingDefAnalysis::getGlobalReachingDefs(MachineInstr *MI, - MCRegister PhysReg, + MCRegister Reg, InstSet &Defs) const { - if (auto *Def = getUniqueReachingMIDef(MI, PhysReg)) { + if (auto *Def = getUniqueReachingMIDef(MI, Reg)) { Defs.insert(Def); return; } for (auto *MBB : MI->getParent()->predecessors()) - getLiveOuts(MBB, PhysReg, Defs); + getLiveOuts(MBB, Reg, Defs); } -void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, - MCRegister PhysReg, InstSet &Defs) const { +void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg, + InstSet &Defs) const { SmallPtrSet VisitedBBs; - getLiveOuts(MBB, PhysReg, Defs, VisitedBBs); + getLiveOuts(MBB, Reg, Defs, VisitedBBs); } -void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, - MCRegister PhysReg, InstSet &Defs, +void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, MCRegister Reg, + InstSet &Defs, BlockSet &VisitedBBs) const { if (VisitedBBs.count(MBB)) return; @@ -425,28 +422,28 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, VisitedBBs.insert(MBB); LiveRegUnits LiveRegs(*TRI); LiveRegs.addLiveOuts(*MBB); - if (LiveRegs.available(PhysReg)) + if (LiveRegs.available(Reg)) return; - if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg)) + if (auto *Def = getLocalLiveOutMIDef(MBB, Reg)) Defs.insert(Def); else for (auto *Pred : MBB->predecessors()) - getLiveOuts(Pred, PhysReg, Defs, VisitedBBs); + getLiveOuts(Pred, Reg, Defs, VisitedBBs); } MachineInstr * ReachingDefAnalysis::getUniqueReachingMIDef(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { // If there's a local def before MI, return it. - MachineInstr *LocalDef = getReachingLocalMIDef(MI, PhysReg); + MachineInstr *LocalDef = getReachingLocalMIDef(MI, Reg); if (LocalDef && InstIds.lookup(LocalDef) < InstIds.lookup(MI)) return LocalDef; SmallPtrSet Incoming; MachineBasicBlock *Parent = MI->getParent(); for (auto *Pred : Parent->predecessors()) - getLiveOuts(Pred, PhysReg, Incoming); + getLiveOuts(Pred, Reg, Incoming); // Check that we have a single incoming value and that it does not // come from the same block as MI - since it would mean that the def @@ -469,13 +466,13 @@ MachineInstr *ReachingDefAnalysis::getMIOperand(MachineInstr *MI, } bool ReachingDefAnalysis::isRegUsedAfter(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { MachineBasicBlock *MBB = MI->getParent(); LiveRegUnits LiveRegs(*TRI); LiveRegs.addLiveOuts(*MBB); // Yes if the register is live out of the basic block. - if (!LiveRegs.available(PhysReg)) + if (!LiveRegs.available(Reg)) return true; // Walk backwards through the block to see if the register is live at some @@ -483,62 +480,61 @@ bool ReachingDefAnalysis::isRegUsedAfter(MachineInstr *MI, for (MachineInstr &Last : instructionsWithoutDebug(MBB->instr_rbegin(), MBB->instr_rend())) { LiveRegs.stepBackward(Last); - if (!LiveRegs.available(PhysReg)) + if (!LiveRegs.available(Reg)) return InstIds.lookup(&Last) > InstIds.lookup(MI); } return false; } bool ReachingDefAnalysis::isRegDefinedAfter(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { MachineBasicBlock *MBB = MI->getParent(); auto Last = MBB->getLastNonDebugInstr(); if (Last != MBB->end() && - getReachingDef(MI, PhysReg) != getReachingDef(&*Last, PhysReg)) + getReachingDef(MI, Reg) != getReachingDef(&*Last, Reg)) return true; - if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg)) - return Def == getReachingLocalMIDef(MI, PhysReg); + if (auto *Def = getLocalLiveOutMIDef(MBB, Reg)) + return Def == getReachingLocalMIDef(MI, Reg); return false; } bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { MachineBasicBlock *MBB = MI->getParent(); LiveRegUnits LiveRegs(*TRI); LiveRegs.addLiveOuts(*MBB); - if (LiveRegs.available(PhysReg)) + if (LiveRegs.available(Reg)) return false; auto Last = MBB->getLastNonDebugInstr(); - int Def = getReachingDef(MI, PhysReg); - if (Last != MBB->end() && getReachingDef(&*Last, PhysReg) != Def) + int Def = getReachingDef(MI, Reg); + if (Last != MBB->end() && getReachingDef(&*Last, Reg) != Def) return false; // Finally check that the last instruction doesn't redefine the register. for (auto &MO : Last->operands()) - if (isValidRegDefOf(MO, PhysReg, TRI)) + if (isValidRegDefOf(MO, Reg, TRI)) return false; return true; } -MachineInstr * -ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB, - MCRegister PhysReg) const { +MachineInstr *ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB, + MCRegister Reg) const { LiveRegUnits LiveRegs(*TRI); LiveRegs.addLiveOuts(*MBB); - if (LiveRegs.available(PhysReg)) + if (LiveRegs.available(Reg)) return nullptr; auto Last = MBB->getLastNonDebugInstr(); if (Last == MBB->end()) return nullptr; - int Def = getReachingDef(&*Last, PhysReg); + int Def = getReachingDef(&*Last, Reg); for (auto &MO : Last->operands()) - if (isValidRegDefOf(MO, PhysReg, TRI)) + if (isValidRegDefOf(MO, Reg, TRI)) return &*Last; return Def < 0 ? nullptr : getInstFromId(MBB, Def); @@ -650,7 +646,7 @@ ReachingDefAnalysis::isSafeToRemove(MachineInstr *MI, InstSet &Visited, void ReachingDefAnalysis::collectKilledOperands(MachineInstr *MI, InstSet &Dead) const { Dead.insert(MI); - auto IsDead = [this, &Dead](MachineInstr *Def, MCRegister PhysReg) { + auto IsDead = [this, &Dead](MachineInstr *Def, MCRegister Reg) { if (mayHaveSideEffects(*Def)) return false; @@ -666,7 +662,7 @@ void ReachingDefAnalysis::collectKilledOperands(MachineInstr *MI, return false; SmallPtrSet Uses; - getGlobalUses(Def, PhysReg, Uses); + getGlobalUses(Def, Reg, Uses); return llvm::set_is_subset(Uses, Dead); }; @@ -680,18 +676,18 @@ void ReachingDefAnalysis::collectKilledOperands(MachineInstr *MI, } bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI, - MCRegister PhysReg) const { + MCRegister Reg) const { SmallPtrSet Ignore; - return isSafeToDefRegAt(MI, PhysReg, Ignore); + return isSafeToDefRegAt(MI, Reg, Ignore); } -bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg, +bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI, MCRegister Reg, InstSet &Ignore) const { // Check for any uses of the register after MI. - if (isRegUsedAfter(MI, PhysReg)) { - if (auto *Def = getReachingLocalMIDef(MI, PhysReg)) { + if (isRegUsedAfter(MI, Reg)) { + if (auto *Def = getReachingLocalMIDef(MI, Reg)) { SmallPtrSet Uses; - getGlobalUses(Def, PhysReg, Uses); + getGlobalUses(Def, Reg, Uses); if (!llvm::set_is_subset(Uses, Ignore)) return false; } else @@ -700,13 +696,13 @@ bool ReachingDefAnalysis::isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg, MachineBasicBlock *MBB = MI->getParent(); // Check for any defs after MI. - if (isRegDefinedAfter(MI, PhysReg)) { + if (isRegDefinedAfter(MI, Reg)) { auto I = MachineBasicBlock::iterator(MI); for (auto E = MBB->end(); I != E; ++I) { if (Ignore.count(&*I)) continue; for (auto &MO : I->operands()) - if (isValidRegDefOf(MO, PhysReg, TRI)) + if (isValidRegDefOf(MO, Reg, TRI)) return false; } } From 322ff423159f618f2dbfdce2031dbd296deb966f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 8 Jan 2025 15:07:11 +0000 Subject: [PATCH 026/163] [PhaseOrdering][AArch64] block_scaling_decompr_8bit.ll - use -passes="default" to allow DOS to correctly evaluate the RUN command Necessary for running update_test_checks.py on windows --- .../PhaseOrdering/AArch64/block_scaling_decompr_8bit.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/block_scaling_decompr_8bit.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/block_scaling_decompr_8bit.ll index 7d9524420286d..9c06e8034be44 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/block_scaling_decompr_8bit.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/block_scaling_decompr_8bit.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 -; RUN: opt -passes='default' -S %s | FileCheck %s +; RUN: opt -passes="default" -S %s | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" target triple = "aarch64" From fe162bed532b78f606fe3d937ba732787dd7bd64 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 8 Jan 2025 16:12:01 +0100 Subject: [PATCH 027/163] Make test more lenient for custom clang version strings The version string can be anything, don't restrict it to digits and dots. It's derived from the resource dir, so just check for that. --- clang/test/Driver/darwin-embedded-search-paths.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/test/Driver/darwin-embedded-search-paths.c b/clang/test/Driver/darwin-embedded-search-paths.c index 7ada467d66de4..7fa20501b52f3 100644 --- a/clang/test/Driver/darwin-embedded-search-paths.c +++ b/clang/test/Driver/darwin-embedded-search-paths.c @@ -33,11 +33,12 @@ // the cc1 arguments. // CC1: "-cc1" +// CC1: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]" // NO-CXX-NOT: "-internal-isystem" "{{.*}}/include/c++/v1" // CXX-SAME: "-internal-isystem" "{{.*}}/include/c++/v1" // ULI-SAME: "-internal-isystem" "[[SDKROOT]]/usr/local/include" // EULI-SAME: "-isystem" "[[SDKROOT]]/embedded/usr/local/include" -// CI-SAME: "-internal-isystem" "{{.*}}/clang/{{[[:digit:].]*}}/include" +// CI-SAME: "-internal-isystem" "[[RESOURCE_DIR]]/include" // UI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/usr/include" // EUI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/embedded/usr/include" // NO-FW-NOT: "-internal-iframework" From a3b4d9147406cbd90090466a9b2b9bb2e9f6000c Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 8 Jan 2025 16:16:46 +0100 Subject: [PATCH 028/163] Fix -Wdangling-assignment-gsl in ClangdLSPServerTests I think this is a false positive for a non-capturing lambda, but I can't find anything in the standard that guarantees that these have eternal lifetime. --- .../clangd/unittests/ClangdLSPServerTests.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp index 49a94045ea487..2c7f50d8c9e4c 100644 --- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp @@ -208,12 +208,13 @@ TEST_F(LSPTest, ClangTidyRename) { Annotations Source(R"cpp( void [[foo]]() {} )cpp"); - Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, - llvm::StringRef) { + constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, + llvm::StringRef) { ClangTidyOpts.Checks = {"-*,readability-identifier-naming"}; ClangTidyOpts.CheckOptions["readability-identifier-naming.FunctionCase"] = "CamelCase"; }; + Opts.ClangTidyProvider = ClangTidyProvider; auto &Client = start(); Client.didOpen("foo.hpp", Header.code()); Client.didOpen("foo.cpp", Source.code()); @@ -266,10 +267,11 @@ TEST_F(LSPTest, ClangTidyCrash_Issue109367) { // This test requires clang-tidy checks to be linked in. if (!CLANGD_TIDY_CHECKS) return; - Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, - llvm::StringRef) { + constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, + llvm::StringRef) { ClangTidyOpts.Checks = {"-*,boost-use-ranges"}; }; + Opts.ClangTidyProvider = ClangTidyProvider; // Check that registering the boost-use-ranges checker's matchers // on two different threads does not cause a crash. auto &Client = start(); From b054289882145f5a1aa8e1d6538ac4714df17059 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Wed, 8 Jan 2025 10:25:31 -0500 Subject: [PATCH 029/163] [libc++] Add missing hardening checks and tests for vector (#121366) This PR adds VALID_ELEMENT_ACCESS and VALID_INPUT_RANGE checks for vector. --- libcxx/include/__vector/vector_bool.h | 35 +++++++++-- .../sequences/vector.bool/assert.pass.cpp | 63 +++++++++++++++++++ 2 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 4c334176a037e..6c6605fb3bd0b 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -275,17 +275,33 @@ class _LIBCPP_TEMPLATE_VIS vector { } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __n) { return __make_ref(__n); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __n) { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector::operator[] index out of bounds"); + return __make_ref(__n); + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __n) const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector::operator[] index out of bounds"); return __make_ref(__n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() { return __make_ref(0); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const { return __make_ref(0); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() { return __make_ref(__size_ - 1); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const { return __make_ref(__size_ - 1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::front() called on an empty vector"); + return __make_ref(0); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::front() called on an empty vector"); + return __make_ref(0); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::back() called on an empty vector"); + return __make_ref(__size_ - 1); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::back() called on an empty vector"); + return __make_ref(__size_ - 1); + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(const value_type& __x); #if _LIBCPP_STD_VER >= 14 @@ -310,7 +326,10 @@ class _LIBCPP_TEMPLATE_VIS vector { } #endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() { --__size_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector"); + --__size_; + } #if _LIBCPP_STD_VER >= 14 template @@ -995,6 +1014,8 @@ vector::__insert_with_size( template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::erase(const_iterator __position) { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); iterator __r = __const_iterator_cast(__position); std::copy(__position + 1, this->cend(), __r); --__size_; @@ -1004,6 +1025,8 @@ vector::erase(const_iterator __position) { template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::iterator vector::erase(const_iterator __first, const_iterator __last) { + _LIBCPP_ASSERT_VALID_INPUT_RANGE( + __first <= __last, "vector::erase(iterator, iterator) called with an invalid range"); iterator __r = __const_iterator_cast(__first); difference_type __d = __last - __first; std::copy(__last, this->cend(), __r); diff --git a/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp new file mode 100644 index 0000000000000..41badad8f569d --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Test hardening assertions for std::vector. + +// REQUIRES: has-unix-headers +// UNSUPPORTED: libcpp-hardening-mode=none +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +template +void test() { + std::vector c; + TEST_LIBCPP_ASSERT_FAILURE(c.front(), "vector::front() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(c.back(), "vector::back() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(c[0], "vector::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(c.pop_back(), "vector::pop_back called on an empty vector"); + + // Repeat the test with a const reference to test the const overloads. + { + const std::vector& cc = c; + TEST_LIBCPP_ASSERT_FAILURE(cc.front(), "vector::front() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(cc.back(), "vector::back() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(cc[0], "vector::operator[] index out of bounds"); + } + + c.push_back(true); + c.push_back(false); + c.push_back(true); + TEST_LIBCPP_ASSERT_FAILURE(c[3], "vector::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(c[100], "vector::operator[] index out of bounds"); + + // Repeat the test with a const reference to test the const overloads. + { + const std::vector& cc = c; + TEST_LIBCPP_ASSERT_FAILURE(cc[3], "vector::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(cc[100], "vector::operator[] index out of bounds"); + } + + TEST_LIBCPP_ASSERT_FAILURE( + c.erase(c.end()), "vector::erase(iterator) called with a non-dereferenceable iterator"); + TEST_LIBCPP_ASSERT_FAILURE( + c.erase(c.begin() + 1, c.begin()), "vector::erase(iterator, iterator) called with an invalid range"); +} + +int main(int, char**) { + test>(); + test>(); + + return 0; +} From 637641840d170491ad99a92a23112e0625d7c6cb Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 8 Jan 2025 22:30:04 +0700 Subject: [PATCH 030/163] AMDGPU: Add baseline test for add64 with constant test (#122048) Add baseline test for 64-bit adds when the low half of an operand is known 0. --- .../AMDGPU/add64-low-32-bits-known-zero.ll | 213 ++++++++++++++++++ .../AMDGPU/sub64-low-32-bits-known-zero.ll | 213 ++++++++++++++++++ 2 files changed, 426 insertions(+) create mode 100644 llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll create mode 100644 llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll diff --git a/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll b/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll new file mode 100644 index 0000000000000..981e33f89d956 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll @@ -0,0 +1,213 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=gfx900 < %s | FileCheck -check-prefix=GFX9 %s + +; Reduce a 64-bit add by a constant if we know the low 32-bits are all +; zero. + +; add i64:x, K if computeTrailingZeros(K) >= 32 +; => build_pair (add x.hi, K.hi), x.lo + +define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_0(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 0x40000 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, 1125899906842624 ; (1 << 50) + ret i64 %add +} + +define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_1(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_low_bits_known0_1: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, 4294967296 ; (1 << 32) + ret i64 %add +} + +define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_2(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_low_bits_known0_2: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 2 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, 8589934592 ; (1 << 33) + ret i64 %add +} + +define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_3(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_low_bits_known0_3: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 0x80000000 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, -9223372036854775808 ; (1 << 63) + ret i64 %add +} + +define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_4(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_low_bits_known0_4: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, -4294967296 ; 0xffffffff00000000 + ret i64 %add +} + +define i64 @v_add_i64_const_low_bits_known0_0(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, 0x40000 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, 1125899906842624 ; (1 << 50) + ret i64 %add +} + +define i64 @v_add_i64_const_low_bits_known0_1(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_low_bits_known0_1: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, 4294967296 ; (1 << 32) + ret i64 %add +} + +define i64 @v_add_i64_const_low_bits_known0_2(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_low_bits_known0_2: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 2, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, 8589934592 ; (1 << 33) + ret i64 %add +} + +define i64 @v_add_i64_const_low_bits_known0_3(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_low_bits_known0_3: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_bfrev_b32_e32 v2, 1 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, -9223372036854775808 ; (1 << 63) + ret i64 %add +} + +define i64 @v_add_i64_const_low_bits_known0_4(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_low_bits_known0_4: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, -4294967296 ; 0xffffffff00000000 + ret i64 %add +} + +define amdgpu_ps i64 @s_add_i64_const_high_bits_known0_0(i64 inreg %reg) { +; GFX9-LABEL: s_add_i64_const_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, -1 +; GFX9-NEXT: s_addc_u32 s1, s1, 0 +; GFX9-NEXT: ; return to shader part epilog + %add = add i64 %reg, 4294967295 ; (1 << 31) + ret i64 %add +} + +define i64 @v_add_i64_const_high_bits_known0_0(i64 %reg) { +; GFX9-LABEL: v_add_i64_const_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, -1, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add i64 %reg, 4294967295 ; (1 << 31) + ret i64 %add +} + +define <2 x i64> @v_add_v2i64_splat_const_low_bits_known0_0(<2 x i64> %reg) { +; GFX9-LABEL: v_add_v2i64_splat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 1, v3, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add <2 x i64> %reg, ; (1 << 32) + ret <2 x i64> %add +} + +define <2 x i64> @v_add_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { +; GFX9-LABEL: v_add_v2i64_nonsplat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 2, v3, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %add = add <2 x i64> %reg, ; (1 << 32), (1 << 33) + ret <2 x i64> %add +} + +define amdgpu_ps <2 x i64> @s_add_v2i64_splat_const_low_bits_known0_0(<2 x i64> inreg %reg) { +; GFX9-LABEL: s_add_v2i64_splat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: s_add_u32 s2, s2, 0 +; GFX9-NEXT: s_addc_u32 s3, s3, 1 +; GFX9-NEXT: ; return to shader part epilog + %add = add <2 x i64> %reg, ; (1 << 32) + ret <2 x i64> %add +} + +define amdgpu_ps <2 x i64> @s_add_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> inreg %reg) { +; GFX9-LABEL: s_add_v2i64_nonsplat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: s_add_u32 s2, s2, 0 +; GFX9-NEXT: s_addc_u32 s3, s3, 2 +; GFX9-NEXT: ; return to shader part epilog + %add = add <2 x i64> %reg, ; (1 << 32), (1 << 33) + ret <2 x i64> %add +} + +; We could reduce this to use a 32-bit add if we use computeKnownBits +define i64 @v_add_i64_variable_high_bits_known0_0(i64 %reg, i32 %offset.hi32) { +; GFX9-LABEL: v_add_i64_variable_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %zext.offset.hi32 = zext i32 %offset.hi32 to i64 + %in.high.bits = shl i64 %zext.offset.hi32, 32 + %add = add i64 %reg, %in.high.bits + ret i64 %add +} + +; We could reduce this to use a 32-bit add if we use computeKnownBits +define amdgpu_ps i64 @s_add_i64_variable_high_bits_known0_0(i64 inreg %reg, i32 inreg %offset.hi32) { +; GFX9-LABEL: s_add_i64_variable_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, s2 +; GFX9-NEXT: ; return to shader part epilog + %zext.offset.hi32 = zext i32 %offset.hi32 to i64 + %in.high.bits = shl i64 %zext.offset.hi32, 32 + %add = add i64 %reg, %in.high.bits + ret i64 %add +} diff --git a/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll b/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll new file mode 100644 index 0000000000000..779c4aef647b4 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll @@ -0,0 +1,213 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=gfx900 < %s | FileCheck -check-prefix=GFX9 %s + +; Reduce a 64-bit sub by a constant if we know the low 32-bits are all +; zero. + +; sub i64:x, K if computeTrailingZeros(K) >= 32 +; => build_pair (sub x.hi, K.hi), x.lo + +define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_0(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 0xfffc0000 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, 1125899906842624 ; (1 << 50) + ret i64 %sub +} + +define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_1(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_low_bits_known0_1: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, 4294967296 ; (1 << 32) + ret i64 %sub +} + +define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_2(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_low_bits_known0_2: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, -2 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, 8589934592 ; (1 << 33) + ret i64 %sub +} + +define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_3(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_low_bits_known0_3: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 0x80000000 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, -9223372036854775808 ; (1 << 63) + ret i64 %sub +} + +define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_4(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_low_bits_known0_4: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, -4294967296 ; 0xffffffff00000000 + ret i64 %sub +} + +define i64 @v_sub_i64_const_low_bits_known0_0(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, 0xfffc0000 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, 1125899906842624 ; (1 << 50) + ret i64 %sub +} + +define i64 @v_sub_i64_const_low_bits_known0_1(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_low_bits_known0_1: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, 4294967296 ; (1 << 32) + ret i64 %sub +} + +define i64 @v_sub_i64_const_low_bits_known0_2(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_low_bits_known0_2: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -2, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, 8589934592 ; (1 << 33) + ret i64 %sub +} + +define i64 @v_sub_i64_const_low_bits_known0_3(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_low_bits_known0_3: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_bfrev_b32_e32 v2, 1 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, -9223372036854775808 ; (1 << 63) + ret i64 %sub +} + +define i64 @v_sub_i64_const_low_bits_known0_4(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_low_bits_known0_4: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, -4294967296 ; 0xffffffff00000000 + ret i64 %sub +} + +define amdgpu_ps i64 @s_sub_i64_const_high_bits_known0_0(i64 inreg %reg) { +; GFX9-LABEL: s_sub_i64_const_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 1 +; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub i64 %reg, 4294967295 ; (1 << 31) + ret i64 %sub +} + +define i64 @v_sub_i64_const_high_bits_known0_0(i64 %reg) { +; GFX9-LABEL: v_sub_i64_const_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub i64 %reg, 4294967295 ; (1 << 31) + ret i64 %sub +} + +define <2 x i64> @v_sub_v2i64_splat_const_low_bits_known0_0(<2 x i64> %reg) { +; GFX9-LABEL: v_sub_v2i64_splat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v3, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub <2 x i64> %reg, ; (1 << 32) + ret <2 x i64> %sub +} + +define <2 x i64> @v_sub_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { +; GFX9-LABEL: v_sub_v2i64_nonsplat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -2, v3, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %sub = sub <2 x i64> %reg, ; (1 << 32), (1 << 33) + ret <2 x i64> %sub +} + +define amdgpu_ps <2 x i64> @s_sub_v2i64_splat_const_low_bits_known0_0(<2 x i64> inreg %reg) { +; GFX9-LABEL: s_sub_v2i64_splat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: s_add_u32 s2, s2, 0 +; GFX9-NEXT: s_addc_u32 s3, s3, -1 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub <2 x i64> %reg, ; (1 << 32) + ret <2 x i64> %sub +} + +define amdgpu_ps <2 x i64> @s_sub_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> inreg %reg) { +; GFX9-LABEL: s_sub_v2i64_nonsplat_const_low_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_add_u32 s0, s0, 0 +; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: s_add_u32 s2, s2, 0 +; GFX9-NEXT: s_addc_u32 s3, s3, -2 +; GFX9-NEXT: ; return to shader part epilog + %sub = sub <2 x i64> %reg, ; (1 << 32), (1 << 33) + ret <2 x i64> %sub +} + +; We could reduce this to use a 32-bit sub if we use computeKnownBits +define i64 @v_sub_i64_variable_high_bits_known0_0(i64 %reg, i32 %offset.hi32) { +; GFX9-LABEL: v_sub_i64_variable_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_subrev_co_u32_e32 v0, vcc, 0, v0 +; GFX9-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: s_setpc_b64 s[30:31] + %zext.offset.hi32 = zext i32 %offset.hi32 to i64 + %in.high.bits = shl i64 %zext.offset.hi32, 32 + %sub = sub i64 %reg, %in.high.bits + ret i64 %sub +} + +; We could reduce this to use a 32-bit sub if we use computeKnownBits +define amdgpu_ps i64 @s_sub_i64_variable_high_bits_known0_0(i64 inreg %reg, i32 inreg %offset.hi32) { +; GFX9-LABEL: s_sub_i64_variable_high_bits_known0_0: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_sub_u32 s0, s0, 0 +; GFX9-NEXT: s_subb_u32 s1, s1, s2 +; GFX9-NEXT: ; return to shader part epilog + %zext.offset.hi32 = zext i32 %offset.hi32 to i64 + %in.high.bits = shl i64 %zext.offset.hi32, 32 + %sub = sub i64 %reg, %in.high.bits + ret i64 %sub +} From 09583dec15c5100fd5f26f81a1b011bce3f9b21f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 8 Jan 2025 22:33:54 +0700 Subject: [PATCH 031/163] AMDGPU: Reduce 64-bit add width if low bits are known 0 (#122049) If one of the inputs has all 0 bits, the low part cannot carry and we can just pass through the original value. Add case: https://alive2.llvm.org/ce/z/TNc7hf Sub case: https://alive2.llvm.org/ce/z/AjH2-J We could do this in the general case with computeKnownBits, but add is so common this could be potentially expensive for something which will fire infrequently. One potential concern is this could break the 64-bit add we expect to see for addressing mode matching, but these constants shouldn't appear often in addressing expressions. One test for large offset expressions changes but isn't worse. Fixes https://github.com/ROCm/llvm-project/issues/237 --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 47 ++++++ llvm/lib/Target/AMDGPU/SIISelLowering.h | 3 + .../AMDGPU/add64-low-32-bits-known-zero.ll | 56 +++---- llvm/test/CodeGen/AMDGPU/global-saddr-load.ll | 54 +++---- .../AMDGPU/promote-constOffset-to-imm.ll | 144 +++++++++--------- .../AMDGPU/sub64-low-32-bits-known-zero.ll | 56 +++---- 6 files changed, 177 insertions(+), 183 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index b3cfa398d9b5f..0ac84f4e1f02a 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -13985,6 +13985,43 @@ SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N, return Accum; } +SDValue +SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N, + DAGCombinerInfo &DCI) const { + SDValue RHS = N->getOperand(1); + auto *CRHS = dyn_cast(RHS); + if (!CRHS) + return SDValue(); + + // TODO: Worth using computeKnownBits? Maybe expensive since it's so + // common. + uint64_t Val = CRHS->getZExtValue(); + if (countr_zero(Val) >= 32) { + SelectionDAG &DAG = DCI.DAG; + SDLoc SL(N); + SDValue LHS = N->getOperand(0); + + // Avoid carry machinery if we know the low half of the add does not + // contribute to the final result. + // + // add i64:x, K if computeTrailingZeros(K) >= 32 + // => build_pair (add x.hi, K.hi), x.lo + + // Breaking the 64-bit add here with this strange constant is unlikely + // to interfere with addressing mode patterns. + + SDValue Hi = getHiHalf64(LHS, DAG); + SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32); + SDValue AddHi = + DAG.getNode(N->getOpcode(), SL, MVT::i32, Hi, ConstHi32, N->getFlags()); + + SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS); + return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi); + } + + return SDValue(); +} + // Collect the ultimate src of each of the mul node's operands, and confirm // each operand is 8 bytes. static std::optional> @@ -14261,6 +14298,11 @@ SDValue SITargetLowering::performAddCombine(SDNode *N, return V; } + if (VT == MVT::i64) { + if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI)) + return Folded; + } + if ((isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() && (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) { SDValue TempNode(N, 0); @@ -14446,6 +14488,11 @@ SDValue SITargetLowering::performSubCombine(SDNode *N, SelectionDAG &DAG = DCI.DAG; EVT VT = N->getValueType(0); + if (VT == MVT::i64) { + if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI)) + return Folded; + } + if (VT != MVT::i32) return SDValue(); diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index f4641e7a65990..299c8f5f73923 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -212,6 +212,9 @@ class SITargetLowering final : public AMDGPUTargetLowering { unsigned getFusedOpcode(const SelectionDAG &DAG, const SDNode *N0, const SDNode *N1) const; SDValue tryFoldToMad64_32(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue foldAddSub64WithZeroLowBitsTo32(SDNode *N, + DAGCombinerInfo &DCI) const; + SDValue performAddCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue performAddCarrySubCarryCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue performSubCombine(SDNode *N, DAGCombinerInfo &DCI) const; diff --git a/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll b/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll index 981e33f89d956..52259c4c2e6e1 100644 --- a/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll +++ b/llvm/test/CodeGen/AMDGPU/add64-low-32-bits-known-zero.ll @@ -10,8 +10,7 @@ define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_0(i64 inreg %reg) { ; GFX9-LABEL: s_add_i64_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 0x40000 +; GFX9-NEXT: s_add_i32 s1, s1, 0x40000 ; GFX9-NEXT: ; return to shader part epilog %add = add i64 %reg, 1125899906842624 ; (1 << 50) ret i64 %add @@ -20,8 +19,7 @@ define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_0(i64 inreg %reg) { define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_1(i64 inreg %reg) { ; GFX9-LABEL: s_add_i64_const_low_bits_known0_1: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: s_add_i32 s1, s1, 1 ; GFX9-NEXT: ; return to shader part epilog %add = add i64 %reg, 4294967296 ; (1 << 32) ret i64 %add @@ -30,8 +28,7 @@ define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_1(i64 inreg %reg) { define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_2(i64 inreg %reg) { ; GFX9-LABEL: s_add_i64_const_low_bits_known0_2: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 2 +; GFX9-NEXT: s_add_i32 s1, s1, 2 ; GFX9-NEXT: ; return to shader part epilog %add = add i64 %reg, 8589934592 ; (1 << 33) ret i64 %add @@ -40,8 +37,7 @@ define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_2(i64 inreg %reg) { define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_3(i64 inreg %reg) { ; GFX9-LABEL: s_add_i64_const_low_bits_known0_3: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s1, 0x80000000 ; GFX9-NEXT: ; return to shader part epilog %add = add i64 %reg, -9223372036854775808 ; (1 << 63) ret i64 %add @@ -50,8 +46,7 @@ define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_3(i64 inreg %reg) { define amdgpu_ps i64 @s_add_i64_const_low_bits_known0_4(i64 inreg %reg) { ; GFX9-LABEL: s_add_i64_const_low_bits_known0_4: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: s_add_i32 s1, s1, -1 ; GFX9-NEXT: ; return to shader part epilog %add = add i64 %reg, -4294967296 ; 0xffffffff00000000 ret i64 %add @@ -61,9 +56,7 @@ define i64 @v_add_i64_const_low_bits_known0_0(i64 %reg) { ; GFX9-LABEL: v_add_i64_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v2, 0x40000 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 0x40000, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add i64 %reg, 1125899906842624 ; (1 << 50) ret i64 %add @@ -73,8 +66,7 @@ define i64 @v_add_i64_const_low_bits_known0_1(i64 %reg) { ; GFX9-LABEL: v_add_i64_const_low_bits_known0_1: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 1, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add i64 %reg, 4294967296 ; (1 << 32) ret i64 %add @@ -84,8 +76,7 @@ define i64 @v_add_i64_const_low_bits_known0_2(i64 %reg) { ; GFX9-LABEL: v_add_i64_const_low_bits_known0_2: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 2, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 2, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add i64 %reg, 8589934592 ; (1 << 33) ret i64 %add @@ -95,9 +86,7 @@ define i64 @v_add_i64_const_low_bits_known0_3(i64 %reg) { ; GFX9-LABEL: v_add_i64_const_low_bits_known0_3: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_bfrev_b32_e32 v2, 1 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add i64 %reg, -9223372036854775808 ; (1 << 63) ret i64 %add @@ -107,8 +96,7 @@ define i64 @v_add_i64_const_low_bits_known0_4(i64 %reg) { ; GFX9-LABEL: v_add_i64_const_low_bits_known0_4: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -1, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add i64 %reg, -4294967296 ; 0xffffffff00000000 ret i64 %add @@ -139,10 +127,8 @@ define <2 x i64> @v_add_v2i64_splat_const_low_bits_known0_0(<2 x i64> %reg) { ; GFX9-LABEL: v_add_v2i64_splat_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 1, v3, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 1, v1 +; GFX9-NEXT: v_add_u32_e32 v3, 1, v3 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add <2 x i64> %reg, ; (1 << 32) ret <2 x i64> %add @@ -152,10 +138,8 @@ define <2 x i64> @v_add_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { ; GFX9-LABEL: v_add_v2i64_nonsplat_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 2, v3, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 1, v1 +; GFX9-NEXT: v_add_u32_e32 v3, 2, v3 ; GFX9-NEXT: s_setpc_b64 s[30:31] %add = add <2 x i64> %reg, ; (1 << 32), (1 << 33) ret <2 x i64> %add @@ -164,10 +148,8 @@ define <2 x i64> @v_add_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { define amdgpu_ps <2 x i64> @s_add_v2i64_splat_const_low_bits_known0_0(<2 x i64> inreg %reg) { ; GFX9-LABEL: s_add_v2i64_splat_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 1 -; GFX9-NEXT: s_add_u32 s2, s2, 0 -; GFX9-NEXT: s_addc_u32 s3, s3, 1 +; GFX9-NEXT: s_add_i32 s1, s1, 1 +; GFX9-NEXT: s_add_i32 s3, s3, 1 ; GFX9-NEXT: ; return to shader part epilog %add = add <2 x i64> %reg, ; (1 << 32) ret <2 x i64> %add @@ -176,10 +158,8 @@ define amdgpu_ps <2 x i64> @s_add_v2i64_splat_const_low_bits_known0_0(<2 x i64> define amdgpu_ps <2 x i64> @s_add_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> inreg %reg) { ; GFX9-LABEL: s_add_v2i64_nonsplat_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 1 -; GFX9-NEXT: s_add_u32 s2, s2, 0 -; GFX9-NEXT: s_addc_u32 s3, s3, 2 +; GFX9-NEXT: s_add_i32 s1, s1, 1 +; GFX9-NEXT: s_add_i32 s3, s3, 2 ; GFX9-NEXT: ; return to shader part epilog %add = add <2 x i64> %reg, ; (1 << 32), (1 << 33) ret <2 x i64> %add diff --git a/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll b/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll index 157f91ccc6b1c..b2f113f08a916 100644 --- a/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll +++ b/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll @@ -668,37 +668,32 @@ define amdgpu_ps float @global_load_saddr_i8_offset_0xFFFFFFFF(ptr addrspace(1) define amdgpu_ps float @global_load_saddr_i8_offset_0x100000000(ptr addrspace(1) inreg %sbase) { ; GFX9-LABEL: global_load_saddr_i8_offset_0x100000000: ; GFX9: ; %bb.0: -; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: v_add_co_u32_e64 v0, vcc, 0, s2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc -; GFX9-NEXT: global_load_ubyte v0, v[0:1], off +; GFX9-NEXT: s_add_i32 s3, s3, 1 +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: global_load_ubyte v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: ; return to shader part epilog ; ; GFX10-LABEL: global_load_saddr_i8_offset_0x100000000: ; GFX10: ; %bb.0: -; GFX10-NEXT: v_add_co_u32 v0, s[0:1], 0, s2 -; GFX10-NEXT: v_add_co_ci_u32_e64 v1, s[0:1], 1, s3, s[0:1] -; GFX10-NEXT: global_load_ubyte v0, v[0:1], off +; GFX10-NEXT: v_mov_b32_e32 v0, 0 +; GFX10-NEXT: s_add_i32 s3, s3, 1 +; GFX10-NEXT: global_load_ubyte v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: ; return to shader part epilog ; ; GFX11-LABEL: global_load_saddr_i8_offset_0x100000000: ; GFX11: ; %bb.0: -; GFX11-NEXT: v_add_co_u32 v0, s[0:1], 0, s2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_add_co_ci_u32_e64 v1, null, 1, s3, s[0:1] -; GFX11-NEXT: global_load_u8 v0, v[0:1], off +; GFX11-NEXT: v_mov_b32_e32 v0, 0 +; GFX11-NEXT: s_add_i32 s3, s3, 1 +; GFX11-NEXT: global_load_u8 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-SDAG-LABEL: global_load_saddr_i8_offset_0x100000000: ; GFX12-SDAG: ; %bb.0: -; GFX12-SDAG-NEXT: s_mov_b32 s0, 0 -; GFX12-SDAG-NEXT: s_mov_b32 s1, 1 -; GFX12-SDAG-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX12-SDAG-NEXT: s_add_nc_u64 s[0:1], s[2:3], s[0:1] -; GFX12-SDAG-NEXT: s_load_u8 s0, s[0:1], 0x0 +; GFX12-SDAG-NEXT: s_add_co_i32 s3, s3, 1 +; GFX12-SDAG-NEXT: s_load_u8 s0, s[2:3], 0x0 ; GFX12-SDAG-NEXT: s_wait_kmcnt 0x0 ; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0 ; GFX12-SDAG-NEXT: ; return to shader part epilog @@ -934,37 +929,32 @@ define amdgpu_ps float @global_load_saddr_i8_offset_neg0xFFFFFFFF(ptr addrspace( define amdgpu_ps float @global_load_saddr_i8_offset_neg0x100000000(ptr addrspace(1) inreg %sbase) { ; GFX9-LABEL: global_load_saddr_i8_offset_neg0x100000000: ; GFX9: ; %bb.0: -; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: v_add_co_u32_e64 v0, vcc, 0, s2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc -; GFX9-NEXT: global_load_ubyte v0, v[0:1], off +; GFX9-NEXT: s_add_i32 s3, s3, -1 +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: global_load_ubyte v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: ; return to shader part epilog ; ; GFX10-LABEL: global_load_saddr_i8_offset_neg0x100000000: ; GFX10: ; %bb.0: -; GFX10-NEXT: v_add_co_u32 v0, s[0:1], 0, s2 -; GFX10-NEXT: v_add_co_ci_u32_e64 v1, s[0:1], -1, s3, s[0:1] -; GFX10-NEXT: global_load_ubyte v0, v[0:1], off +; GFX10-NEXT: v_mov_b32_e32 v0, 0 +; GFX10-NEXT: s_add_i32 s3, s3, -1 +; GFX10-NEXT: global_load_ubyte v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: ; return to shader part epilog ; ; GFX11-LABEL: global_load_saddr_i8_offset_neg0x100000000: ; GFX11: ; %bb.0: -; GFX11-NEXT: v_add_co_u32 v0, s[0:1], 0, s2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_add_co_ci_u32_e64 v1, null, -1, s3, s[0:1] -; GFX11-NEXT: global_load_u8 v0, v[0:1], off +; GFX11-NEXT: v_mov_b32_e32 v0, 0 +; GFX11-NEXT: s_add_i32 s3, s3, -1 +; GFX11-NEXT: global_load_u8 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-SDAG-LABEL: global_load_saddr_i8_offset_neg0x100000000: ; GFX12-SDAG: ; %bb.0: -; GFX12-SDAG-NEXT: s_mov_b32 s0, 0 -; GFX12-SDAG-NEXT: s_mov_b32 s1, -1 -; GFX12-SDAG-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX12-SDAG-NEXT: s_add_nc_u64 s[0:1], s[2:3], s[0:1] -; GFX12-SDAG-NEXT: s_load_u8 s0, s[0:1], 0x0 +; GFX12-SDAG-NEXT: s_add_co_i32 s3, s3, -1 +; GFX12-SDAG-NEXT: s_load_u8 s0, s[2:3], 0x0 ; GFX12-SDAG-NEXT: s_wait_kmcnt 0x0 ; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0 ; GFX12-SDAG-NEXT: ; return to shader part epilog diff --git a/llvm/test/CodeGen/AMDGPU/promote-constOffset-to-imm.ll b/llvm/test/CodeGen/AMDGPU/promote-constOffset-to-imm.ll index 98d5f3097153d..a2a0107a6f7d8 100644 --- a/llvm/test/CodeGen/AMDGPU/promote-constOffset-to-imm.ll +++ b/llvm/test/CodeGen/AMDGPU/promote-constOffset-to-imm.ll @@ -1372,20 +1372,19 @@ define amdgpu_kernel void @Offset64(ptr addrspace(1) %buffer) { ; GFX8-NEXT: v_add_u32_e32 v3, vcc, v1, v0 ; GFX8-NEXT: v_addc_u32_e32 v4, vcc, 0, v2, vcc ; GFX8-NEXT: s_movk_i32 s0, 0xf000 -; GFX8-NEXT: v_add_u32_e32 v5, vcc, s0, v3 -; GFX8-NEXT: v_addc_u32_e32 v6, vcc, 0, v4, vcc +; GFX8-NEXT: v_add_u32_e32 v7, vcc, s0, v3 +; GFX8-NEXT: v_addc_u32_e32 v8, vcc, 0, v4, vcc ; GFX8-NEXT: s_movk_i32 s0, 0xf800 -; GFX8-NEXT: flat_load_dwordx2 v[7:8], v[3:4] -; GFX8-NEXT: flat_load_dwordx2 v[5:6], v[5:6] +; GFX8-NEXT: flat_load_dwordx2 v[5:6], v[3:4] +; GFX8-NEXT: flat_load_dwordx2 v[7:8], v[7:8] ; GFX8-NEXT: v_add_u32_e32 v9, vcc, s0, v3 ; GFX8-NEXT: v_addc_u32_e32 v10, vcc, 0, v4, vcc ; GFX8-NEXT: flat_load_dwordx2 v[9:10], v[9:10] -; GFX8-NEXT: v_add_u32_e32 v3, vcc, 0, v3 -; GFX8-NEXT: v_addc_u32_e32 v4, vcc, 1, v4, vcc +; GFX8-NEXT: v_add_u32_e32 v4, vcc, 1, v4 ; GFX8-NEXT: flat_load_dwordx2 v[3:4], v[3:4] ; GFX8-NEXT: s_waitcnt vmcnt(2) -; GFX8-NEXT: v_add_u32_e32 v0, vcc, v5, v7 -; GFX8-NEXT: v_addc_u32_e32 v5, vcc, v6, v8, vcc +; GFX8-NEXT: v_add_u32_e32 v0, vcc, v7, v5 +; GFX8-NEXT: v_addc_u32_e32 v5, vcc, v8, v6, vcc ; GFX8-NEXT: s_waitcnt vmcnt(1) ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v9, v0 ; GFX8-NEXT: v_addc_u32_e32 v5, vcc, v10, v5, vcc @@ -1416,32 +1415,32 @@ define amdgpu_kernel void @Offset64(ptr addrspace(1) %buffer) { ; GFX9-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] ; GFX9-NEXT: v_lshlrev_b32_e32 v1, 7, v0 -; GFX9-NEXT: v_and_b32_e32 v12, 0xffff8000, v1 +; GFX9-NEXT: v_and_b32_e32 v10, 0xffff8000, v1 ; GFX9-NEXT: v_mov_b32_e32 v1, s35 -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s34, v12 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s34, v10 ; GFX9-NEXT: v_mov_b32_e32 v3, 3 ; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: v_lshlrev_b32_sdwa v0, v3, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v2, v0 ; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v4, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v5, vcc, 1, v1, vcc -; GFX9-NEXT: global_load_dwordx2 v[2:3], v[0:1], off -; GFX9-NEXT: global_load_dwordx2 v[6:7], v[4:5], off offset:-4096 ; GFX9-NEXT: s_movk_i32 s0, 0xf000 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc -; GFX9-NEXT: global_load_dwordx2 v[8:9], v[4:5], off -; GFX9-NEXT: global_load_dwordx2 v[10:11], v[0:1], off offset:2048 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[2:3], off +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off +; GFX9-NEXT: global_load_dwordx2 v[8:9], v[2:3], off offset:2048 +; GFX9-NEXT: v_add_u32_e32 v1, 1, v1 +; GFX9-NEXT: global_load_dwordx2 v[0:1], v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(2) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v6, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v7, v3, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, v4, v6 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v5, v7, vcc +; GFX9-NEXT: s_waitcnt vmcnt(1) +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, v8, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v9, v3, vcc ; GFX9-NEXT: s_waitcnt vmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v10, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v11, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v8, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v9, v1, vcc -; GFX9-NEXT: global_store_dwordx2 v12, v[0:1], s[34:35] +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: global_store_dwordx2 v10, v[0:1], s[34:35] ; GFX9-NEXT: s_endpgm ; ; GFX10-LABEL: Offset64: @@ -1477,8 +1476,7 @@ define amdgpu_kernel void @Offset64(ptr addrspace(1) %buffer) { ; GFX10-NEXT: s_clause 0x1 ; GFX10-NEXT: global_load_dwordx2 v[4:5], v[0:1], off ; GFX10-NEXT: global_load_dwordx2 v[6:7], v[2:3], off offset:-2048 -; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, 0, v0 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 1, v1, vcc_lo +; GFX10-NEXT: v_add_nc_u32_e32 v1, 1, v1 ; GFX10-NEXT: s_clause 0x1 ; GFX10-NEXT: global_load_dwordx2 v[8:9], v[2:3], off ; GFX10-NEXT: global_load_dwordx2 v[10:11], v[0:1], off @@ -1517,25 +1515,25 @@ define amdgpu_kernel void @Offset64(ptr addrspace(1) %buffer) { ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v1, v0 ; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v2, vcc_lo ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v4, vcc_lo, v0, 0 -; GFX11-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, 1, v1, vcc_lo -; GFX11-NEXT: global_load_b64 v[2:3], v[0:1], off -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, 0xfffff000, v0 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo +; GFX11-NEXT: v_add_co_u32 v2, vcc_lo, 0xfffff000, v0 +; GFX11-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, 0, v1, vcc_lo ; GFX11-NEXT: s_clause 0x2 -; GFX11-NEXT: global_load_b64 v[6:7], v[4:5], off offset:-4096 -; GFX11-NEXT: global_load_b64 v[4:5], v[4:5], off -; GFX11-NEXT: global_load_b64 v[0:1], v[0:1], off offset:2048 +; GFX11-NEXT: global_load_b64 v[4:5], v[2:3], off +; GFX11-NEXT: global_load_b64 v[6:7], v[0:1], off +; GFX11-NEXT: global_load_b64 v[2:3], v[2:3], off offset:2048 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 1, v1 +; GFX11-NEXT: global_load_b64 v[0:1], v[0:1], off ; GFX11-NEXT: s_waitcnt vmcnt(2) -; GFX11-NEXT: v_add_co_u32 v2, vcc_lo, v6, v2 -; GFX11-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, v7, v3, vcc_lo +; GFX11-NEXT: v_add_co_u32 v4, vcc_lo, v4, v6 +; GFX11-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, v5, v7, vcc_lo +; GFX11-NEXT: s_waitcnt vmcnt(1) +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; GFX11-NEXT: v_add_co_u32 v2, vcc_lo, v2, v4 +; GFX11-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, v3, v5, vcc_lo ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 ; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v4, v0 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v5, v1, vcc_lo ; GFX11-NEXT: global_store_b64 v8, v[0:1], s[34:35] ; GFX11-NEXT: s_endpgm entry: @@ -2408,18 +2406,17 @@ define hidden amdgpu_kernel void @negativeoffset(ptr addrspace(1) nocapture %buf ; GFX8-NEXT: v_mov_b32_e32 v3, 3 ; GFX8-NEXT: v_addc_u32_e32 v2, vcc, 0, v2, vcc ; GFX8-NEXT: v_lshlrev_b32_sdwa v0, v3, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 -; GFX8-NEXT: v_add_u32_e32 v0, vcc, v1, v0 -; GFX8-NEXT: v_addc_u32_e32 v6, vcc, 0, v2, vcc +; GFX8-NEXT: v_add_u32_e32 v3, vcc, v1, v0 +; GFX8-NEXT: v_addc_u32_e32 v0, vcc, 0, v2, vcc ; GFX8-NEXT: s_movk_i32 s0, 0x800 -; GFX8-NEXT: v_add_u32_e32 v3, vcc, s0, v0 -; GFX8-NEXT: v_addc_u32_e32 v4, vcc, -1, v6, vcc -; GFX8-NEXT: v_add_u32_e32 v5, vcc, 0, v0 -; GFX8-NEXT: v_addc_u32_e32 v6, vcc, -1, v6, vcc -; GFX8-NEXT: flat_load_dwordx2 v[3:4], v[3:4] +; GFX8-NEXT: v_add_u32_e32 v5, vcc, s0, v3 +; GFX8-NEXT: v_addc_u32_e32 v6, vcc, -1, v0, vcc +; GFX8-NEXT: v_add_u32_e32 v4, vcc, -1, v0 ; GFX8-NEXT: flat_load_dwordx2 v[5:6], v[5:6] +; GFX8-NEXT: flat_load_dwordx2 v[3:4], v[3:4] ; GFX8-NEXT: s_waitcnt vmcnt(0) -; GFX8-NEXT: v_add_u32_e32 v3, vcc, v5, v3 -; GFX8-NEXT: v_addc_u32_e32 v4, vcc, v6, v4, vcc +; GFX8-NEXT: v_add_u32_e32 v3, vcc, v3, v5 +; GFX8-NEXT: v_addc_u32_e32 v4, vcc, v4, v6, vcc ; GFX8-NEXT: flat_store_dwordx2 v[1:2], v[3:4] ; GFX8-NEXT: s_endpgm ; @@ -2450,14 +2447,13 @@ define hidden amdgpu_kernel void @negativeoffset(ptr addrspace(1) nocapture %buf ; GFX9-NEXT: v_mov_b32_e32 v3, 3 ; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: v_lshlrev_b32_sdwa v0, v3, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, v2, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0x1000, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v3, vcc -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v3, vcc -; GFX9-NEXT: global_load_dwordx2 v[4:5], v[0:1], off offset:-2048 -; GFX9-NEXT: global_load_dwordx2 v[6:7], v[2:3], off +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0x1000, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -1, v1 +; GFX9-NEXT: global_load_dwordx2 v[4:5], v[2:3], off offset:-2048 +; GFX9-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v6, v4 ; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v7, v5, vcc @@ -2490,15 +2486,14 @@ define hidden amdgpu_kernel void @negativeoffset(ptr addrspace(1) nocapture %buf ; GFX10-NEXT: v_lshlrev_b32_sdwa v0, v2, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 ; GFX10-NEXT: v_add_co_u32 v1, s0, s34, v8 ; GFX10-NEXT: v_add_co_ci_u32_e64 v2, s0, s35, 0, s0 -; GFX10-NEXT: v_add_co_u32 v3, vcc_lo, v1, v0 -; GFX10-NEXT: v_add_co_ci_u32_e32 v4, vcc_lo, 0, v2, vcc_lo -; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, 0x800, v3 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, -1, v4, vcc_lo -; GFX10-NEXT: v_add_co_u32 v2, vcc_lo, 0, v3 -; GFX10-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, -1, v4, vcc_lo +; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v1, v0 +; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v2, vcc_lo +; GFX10-NEXT: v_add_co_u32 v2, vcc_lo, 0x800, v0 +; GFX10-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, -1, v1, vcc_lo +; GFX10-NEXT: v_add_nc_u32_e32 v1, -1, v1 ; GFX10-NEXT: s_clause 0x1 -; GFX10-NEXT: global_load_dwordx2 v[4:5], v[0:1], off -; GFX10-NEXT: global_load_dwordx2 v[6:7], v[2:3], off +; GFX10-NEXT: global_load_dwordx2 v[4:5], v[2:3], off +; GFX10-NEXT: global_load_dwordx2 v[6:7], v[0:1], off ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v6, v4 ; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v7, v5, vcc_lo @@ -2525,19 +2520,18 @@ define hidden amdgpu_kernel void @negativeoffset(ptr addrspace(1) nocapture %buf ; GFX11-NEXT: v_add_co_u32 v1, s0, s34, v4 ; GFX11-NEXT: v_add_co_ci_u32_e64 v2, null, s35, 0, s0 ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v3, vcc_lo, v1, v0 -; GFX11-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, 0, v2, vcc_lo +; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v1, v0 +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v2, vcc_lo ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, 0x1000, v3 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, -1, v5, vcc_lo -; GFX11-NEXT: v_add_co_u32 v2, vcc_lo, 0, v3 -; GFX11-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, -1, v5, vcc_lo +; GFX11-NEXT: v_add_co_u32 v2, vcc_lo, 0x1000, v0 +; GFX11-NEXT: v_add_co_ci_u32_e32 v3, vcc_lo, -1, v1, vcc_lo +; GFX11-NEXT: v_add_nc_u32_e32 v1, -1, v1 ; GFX11-NEXT: s_clause 0x1 -; GFX11-NEXT: global_load_b64 v[0:1], v[0:1], off offset:-2048 -; GFX11-NEXT: global_load_b64 v[2:3], v[2:3], off +; GFX11-NEXT: global_load_b64 v[2:3], v[2:3], off offset:-2048 +; GFX11-NEXT: global_load_b64 v[0:1], v[0:1], off ; GFX11-NEXT: s_waitcnt vmcnt(0) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v2, v0 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v3, v1, vcc_lo +; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo ; GFX11-NEXT: global_store_b64 v4, v[0:1], s[34:35] ; GFX11-NEXT: s_endpgm entry: diff --git a/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll b/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll index 779c4aef647b4..f52f1164f2ba2 100644 --- a/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll +++ b/llvm/test/CodeGen/AMDGPU/sub64-low-32-bits-known-zero.ll @@ -10,8 +10,7 @@ define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_0(i64 inreg %reg) { ; GFX9-LABEL: s_sub_i64_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 0xfffc0000 +; GFX9-NEXT: s_add_i32 s1, s1, 0xfffc0000 ; GFX9-NEXT: ; return to shader part epilog %sub = sub i64 %reg, 1125899906842624 ; (1 << 50) ret i64 %sub @@ -20,8 +19,7 @@ define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_0(i64 inreg %reg) { define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_1(i64 inreg %reg) { ; GFX9-LABEL: s_sub_i64_const_low_bits_known0_1: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, -1 +; GFX9-NEXT: s_add_i32 s1, s1, -1 ; GFX9-NEXT: ; return to shader part epilog %sub = sub i64 %reg, 4294967296 ; (1 << 32) ret i64 %sub @@ -30,8 +28,7 @@ define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_1(i64 inreg %reg) { define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_2(i64 inreg %reg) { ; GFX9-LABEL: s_sub_i64_const_low_bits_known0_2: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, -2 +; GFX9-NEXT: s_add_i32 s1, s1, -2 ; GFX9-NEXT: ; return to shader part epilog %sub = sub i64 %reg, 8589934592 ; (1 << 33) ret i64 %sub @@ -40,8 +37,7 @@ define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_2(i64 inreg %reg) { define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_3(i64 inreg %reg) { ; GFX9-LABEL: s_sub_i64_const_low_bits_known0_3: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s1, 0x80000000 ; GFX9-NEXT: ; return to shader part epilog %sub = sub i64 %reg, -9223372036854775808 ; (1 << 63) ret i64 %sub @@ -50,8 +46,7 @@ define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_3(i64 inreg %reg) { define amdgpu_ps i64 @s_sub_i64_const_low_bits_known0_4(i64 inreg %reg) { ; GFX9-LABEL: s_sub_i64_const_low_bits_known0_4: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, 1 +; GFX9-NEXT: s_add_i32 s1, s1, 1 ; GFX9-NEXT: ; return to shader part epilog %sub = sub i64 %reg, -4294967296 ; 0xffffffff00000000 ret i64 %sub @@ -61,9 +56,7 @@ define i64 @v_sub_i64_const_low_bits_known0_0(i64 %reg) { ; GFX9-LABEL: v_sub_i64_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v2, 0xfffc0000 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 0xfffc0000, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub i64 %reg, 1125899906842624 ; (1 << 50) ret i64 %sub @@ -73,8 +66,7 @@ define i64 @v_sub_i64_const_low_bits_known0_1(i64 %reg) { ; GFX9-LABEL: v_sub_i64_const_low_bits_known0_1: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -1, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub i64 %reg, 4294967296 ; (1 << 32) ret i64 %sub @@ -84,8 +76,7 @@ define i64 @v_sub_i64_const_low_bits_known0_2(i64 %reg) { ; GFX9-LABEL: v_sub_i64_const_low_bits_known0_2: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -2, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -2, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub i64 %reg, 8589934592 ; (1 << 33) ret i64 %sub @@ -95,9 +86,7 @@ define i64 @v_sub_i64_const_low_bits_known0_3(i64 %reg) { ; GFX9-LABEL: v_sub_i64_const_low_bits_known0_3: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_bfrev_b32_e32 v2, 1 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v2, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub i64 %reg, -9223372036854775808 ; (1 << 63) ret i64 %sub @@ -107,8 +96,7 @@ define i64 @v_sub_i64_const_low_bits_known0_4(i64 %reg) { ; GFX9-LABEL: v_sub_i64_const_low_bits_known0_4: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 1, v1, vcc +; GFX9-NEXT: v_add_u32_e32 v1, 1, v1 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub i64 %reg, -4294967296 ; 0xffffffff00000000 ret i64 %sub @@ -139,10 +127,8 @@ define <2 x i64> @v_sub_v2i64_splat_const_low_bits_known0_0(<2 x i64> %reg) { ; GFX9-LABEL: v_sub_v2i64_splat_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v3, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -1, v1 +; GFX9-NEXT: v_add_u32_e32 v3, -1, v3 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub <2 x i64> %reg, ; (1 << 32) ret <2 x i64> %sub @@ -152,10 +138,8 @@ define <2 x i64> @v_sub_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { ; GFX9-LABEL: v_sub_v2i64_nonsplat_const_low_bits_known0_0: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, 0, v0 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v1, vcc -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, 0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, -2, v3, vcc +; GFX9-NEXT: v_add_u32_e32 v1, -1, v1 +; GFX9-NEXT: v_add_u32_e32 v3, -2, v3 ; GFX9-NEXT: s_setpc_b64 s[30:31] %sub = sub <2 x i64> %reg, ; (1 << 32), (1 << 33) ret <2 x i64> %sub @@ -164,10 +148,8 @@ define <2 x i64> @v_sub_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> %reg) { define amdgpu_ps <2 x i64> @s_sub_v2i64_splat_const_low_bits_known0_0(<2 x i64> inreg %reg) { ; GFX9-LABEL: s_sub_v2i64_splat_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, -1 -; GFX9-NEXT: s_add_u32 s2, s2, 0 -; GFX9-NEXT: s_addc_u32 s3, s3, -1 +; GFX9-NEXT: s_add_i32 s1, s1, -1 +; GFX9-NEXT: s_add_i32 s3, s3, -1 ; GFX9-NEXT: ; return to shader part epilog %sub = sub <2 x i64> %reg, ; (1 << 32) ret <2 x i64> %sub @@ -176,10 +158,8 @@ define amdgpu_ps <2 x i64> @s_sub_v2i64_splat_const_low_bits_known0_0(<2 x i64> define amdgpu_ps <2 x i64> @s_sub_v2i64_nonsplat_const_low_bits_known0_0(<2 x i64> inreg %reg) { ; GFX9-LABEL: s_sub_v2i64_nonsplat_const_low_bits_known0_0: ; GFX9: ; %bb.0: -; GFX9-NEXT: s_add_u32 s0, s0, 0 -; GFX9-NEXT: s_addc_u32 s1, s1, -1 -; GFX9-NEXT: s_add_u32 s2, s2, 0 -; GFX9-NEXT: s_addc_u32 s3, s3, -2 +; GFX9-NEXT: s_add_i32 s1, s1, -1 +; GFX9-NEXT: s_add_i32 s3, s3, -2 ; GFX9-NEXT: ; return to shader part epilog %sub = sub <2 x i64> %reg, ; (1 << 32), (1 << 33) ret <2 x i64> %sub From a5c3cbf7e0df23ca898e4f65e78531641fe4bf60 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 8 Jan 2025 16:38:25 +0100 Subject: [PATCH 032/163] [Loads] Drop dead Offset argument (NFC) The argument is always zero now. --- llvm/lib/Analysis/Loads.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 54b9521fda8fd..bc03e4052a705 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -25,10 +25,9 @@ using namespace llvm; -static bool isAligned(const Value *Base, const APInt &Offset, Align Alignment, +static bool isAligned(const Value *Base, Align Alignment, const DataLayout &DL) { - Align BA = Base->getPointerAlignment(DL); - return BA >= Alignment && Offset.isAligned(BA); + return Base->getPointerAlignment(DL) >= Alignment; } /// Test if V is always a pointer to allocated and suitably aligned memory for @@ -118,8 +117,7 @@ static bool isDereferenceableAndAlignedPointer( // As we recursed through GEPs to get here, we've incrementally checked // that each step advanced by a multiple of the alignment. If our base is // properly aligned, then the original offset accessed must also be. - APInt Offset(DL.getTypeStoreSizeInBits(V->getType()), 0); - return isAligned(V, Offset, Alignment, DL); + return isAligned(V, Alignment, DL); } /// TODO refactor this function to be able to search independently for @@ -154,8 +152,7 @@ static bool isDereferenceableAndAlignedPointer( // checked that each step advanced by a multiple of the alignment. If // our base is properly aligned, then the original offset accessed // must also be. - APInt Offset(DL.getTypeStoreSizeInBits(V->getType()), 0); - return isAligned(V, Offset, Alignment, DL); + return isAligned(V, Alignment, DL); } } } From 92e575d7e44b0230a27cfb8f6f2e2e3367b19967 Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Wed, 8 Jan 2025 10:51:17 -0500 Subject: [PATCH 033/163] [HLSL] Add SPIR-V version of getPointer. (#121963) Use the spv version of the resource.getpointer intrinsic when targeting SPIR-V. --- clang/lib/CodeGen/CGBuiltin.cpp | 5 +++-- clang/lib/CodeGen/CGHLSLRuntime.h | 2 ++ .../CodeGenHLSL/builtins/RWBuffer-subscript.hlsl | 15 ++++++++++----- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 4 ++++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index dcea32969fb99..573be932f8b1a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19212,8 +19212,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, // TODO: Map to an hlsl_device address space. llvm::Type *RetTy = llvm::PointerType::getUnqual(getLLVMContext()); - return Builder.CreateIntrinsic(RetTy, Intrinsic::dx_resource_getpointer, - ArrayRef{HandleOp, IndexOp}); + return Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(), + ArrayRef{HandleOp, IndexOp}); } case Builtin::BI__builtin_hlsl_all: { Value *Op0 = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 3d5724118611c..46e472f0aae21 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -104,6 +104,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp) GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp) + GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer, + resource_getpointer) GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, resource_handlefrombinding) GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl index 4428b77dd9ec8..2ad5b82a02912 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=DXC,CHECK +// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK RWBuffer In; RWBuffer Out; @@ -7,15 +8,19 @@ RWBuffer Out; void main(unsigned GI : SV_GroupIndex) { // CHECK: define void @main() - // CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // DXC: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]] - // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]] Out[GI] = In[GI]; - // CHECK: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // DXC: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[INPTR:.*]] = call ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]] - // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]] Out[GI] = In.Load(GI); } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index c72179e3e18a3..b4d2dce66a6f0 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -118,6 +118,10 @@ let TargetPrefix = "spv" in { : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; + def int_spv_resource_getpointer + : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty], + [IntrNoMem]>; + // Read a value from the image buffer. It does not translate directly to a // single OpImageRead because the result type is not necessarily a 4 element // vector. From f993a8baddb2cc19257da2d7f3935fe3f4154922 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 8 Jan 2025 17:06:22 +0100 Subject: [PATCH 034/163] [Lint] Lint mismatch in ABI attributes (#121929) Detect cases where ABI attributes between the call-site and the called function differ. For now this only handles argument attributes. Inspired by https://discourse.llvm.org/t/difference-between-call-site-attributes-and-declaration-attributes/83902. --- llvm/lib/Analysis/Lint.cpp | 24 ++++++ llvm/test/Analysis/Lint/abi-attrs.ll | 106 +++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 llvm/test/Analysis/Lint/abi-attrs.ll diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp index 4689451243cd9..e9d96a0c2972a 100644 --- a/llvm/lib/Analysis/Lint.cpp +++ b/llvm/lib/Analysis/Lint.cpp @@ -266,6 +266,30 @@ void Lint::visitCallBase(CallBase &I) { visitMemoryReference(I, Loc, DL->getABITypeAlign(Ty), Ty, MemRef::Read | MemRef::Write); } + + // Check that ABI attributes for the function and call-site match. + unsigned ArgNo = AI->getOperandNo(); + Attribute::AttrKind ABIAttributes[] = { + Attribute::ZExt, Attribute::SExt, Attribute::InReg, + Attribute::ByVal, Attribute::ByRef, Attribute::InAlloca, + Attribute::Preallocated, Attribute::StructRet}; + AttributeList CallAttrs = I.getAttributes(); + for (Attribute::AttrKind Attr : ABIAttributes) { + Attribute CallAttr = CallAttrs.getParamAttr(ArgNo, Attr); + Attribute FnAttr = F->getParamAttribute(ArgNo, Attr); + Check(CallAttr.isValid() == FnAttr.isValid(), + Twine("Undefined behavior: ABI attribute ") + + Attribute::getNameFromAttrKind(Attr) + + " not present on both function and call-site", + &I); + if (CallAttr.isValid() && FnAttr.isValid()) { + Check(CallAttr == FnAttr, + Twine("Undefined behavior: ABI attribute ") + + Attribute::getNameFromAttrKind(Attr) + + " does not have same argument for function and call-site", + &I); + } + } } } } diff --git a/llvm/test/Analysis/Lint/abi-attrs.ll b/llvm/test/Analysis/Lint/abi-attrs.ll new file mode 100644 index 0000000000000..5a3ece6602f9c --- /dev/null +++ b/llvm/test/Analysis/Lint/abi-attrs.ll @@ -0,0 +1,106 @@ +; RUN: opt < %s -passes=lint -disable-output 2>&1 | FileCheck %s + +declare void @fn_nothing_i8(i8 %x) +declare void @fn_zeroext(i8 zeroext %x) +declare void @fn_signext(i8 signext %x) +declare void @fn_inreg(i8 inreg %x) + +declare void @fn_nothing_ptr(ptr %x) +declare void @fn_byval(ptr byval(i8) %x) +declare void @fn_byref(ptr byref(i8) %x) +declare void @fn_inalloca(ptr inalloca(i8) %x) +declare void @fn_preallocated(ptr preallocated(i8) %x) +declare void @fn_sret(ptr sret(i8) %x) + +define void @caller_zeroext(i8 %x) { +; CHECK: Undefined behavior: ABI attribute zeroext not present on both function and call-site +; CHECK: call void @fn_zeroext(i8 %x) + call void @fn_zeroext(i8 %x) + +; CHECK: Undefined behavior: ABI attribute zeroext not present on both function and call-site +; CHECK: call void @fn_nothing_i8(i8 zeroext %x) + call void @fn_nothing_i8(i8 zeroext %x) + ret void +} + +define void @caller_signext(i8 %x) { +; CHECK: Undefined behavior: ABI attribute signext not present on both function and call-site +; CHECK: call void @fn_signext(i8 %x) + call void @fn_signext(i8 %x) + +; CHECK: Undefined behavior: ABI attribute signext not present on both function and call-site +; CHECK: call void @fn_nothing_i8(i8 signext %x) + call void @fn_nothing_i8(i8 signext %x) + ret void +} + +define void @caller_inreg(i8 %x) { +; CHECK: Undefined behavior: ABI attribute inreg not present on both function and call-site +; CHECK: call void @fn_inreg(i8 %x) + call void @fn_inreg(i8 %x) + +; CHECK: Undefined behavior: ABI attribute inreg not present on both function and call-site +; CHECK: call void @fn_nothing_i8(i8 inreg %x) + call void @fn_nothing_i8(i8 inreg %x) + ret void +} + +define void @caller_byval(ptr %x) { +; CHECK: Undefined behavior: ABI attribute byval not present on both function and call-site +; CHECK: call void @fn_byval(ptr %x) + call void @fn_byval(ptr %x) + +; CHECK: Undefined behavior: ABI attribute byval not present on both function and call-site +; CHECK: call void @fn_nothing_ptr(ptr byval(i8) %x) + call void @fn_nothing_ptr(ptr byval(i8) %x) + +; CHECK: Undefined behavior: ABI attribute byval does not have same argument for function and call-site +; CHECK: call void @fn_byval(ptr byval(i16) %x) + call void @fn_byval(ptr byval(i16) %x) + ret void +} + +define void @caller_byref(ptr %x) { +; CHECK: Undefined behavior: ABI attribute byref not present on both function and call-site +; CHECK: call void @fn_byref(ptr %x) + call void @fn_byref(ptr %x) + +; CHECK: Undefined behavior: ABI attribute byref not present on both function and call-site +; CHECK: call void @fn_nothing_ptr(ptr byref(i8) %x) + call void @fn_nothing_ptr(ptr byref(i8) %x) + +; CHECK: Undefined behavior: ABI attribute byref does not have same argument for function and call-site +; CHECK: call void @fn_byref(ptr byref(i16) %x) + call void @fn_byref(ptr byref(i16) %x) + ret void +} + +define void @caller_inalloca(ptr %x) { +; CHECK: Undefined behavior: ABI attribute inalloca not present on both function and call-site +; CHECK: call void @fn_inalloca(ptr %x) + call void @fn_inalloca(ptr %x) + +; CHECK: Undefined behavior: ABI attribute inalloca not present on both function and call-site +; CHECK: call void @fn_nothing_ptr(ptr inalloca(i8) %x) + call void @fn_nothing_ptr(ptr inalloca(i8) %x) + +; CHECK: Undefined behavior: ABI attribute inalloca does not have same argument for function and call-site +; CHECK: call void @fn_inalloca(ptr inalloca(i16) %x) + call void @fn_inalloca(ptr inalloca(i16) %x) + ret void +} + +define void @caller_sret(ptr %x) { +; CHECK: Undefined behavior: ABI attribute sret not present on both function and call-site +; CHECK: call void @fn_sret(ptr %x) + call void @fn_sret(ptr %x) + +; CHECK: Undefined behavior: ABI attribute sret not present on both function and call-site +; CHECK: call void @fn_nothing_ptr(ptr sret(i8) %x) + call void @fn_nothing_ptr(ptr sret(i8) %x) + +; CHECK: Undefined behavior: ABI attribute sret does not have same argument for function and call-site +; CHECK: call void @fn_sret(ptr sret(i16) %x) + call void @fn_sret(ptr sret(i16) %x) + ret void +} From 4751f47c7af63315565891a1d112376b52e6b826 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Wed, 8 Jan 2025 17:10:06 +0100 Subject: [PATCH 035/163] [mlir][Transforms] Dialect conversion: Turn LLVM_DEPRECATED into comments (#122073) Some functions of the deprecated 1:N dialect conversion were marked as `LLVM_DEPRECATED`. This caused compilation warnings because there are still test cases of the 1:N dialect conversion framework. (These test cases will be deleted at the same time when the 1:N driver is deleted.) --- mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h | 3 +-- mlir/include/mlir/Transforms/OneToNTypeConversion.h | 11 +++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h b/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h index 9c1479d28c305..18c9dfd205de3 100644 --- a/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h +++ b/mlir/include/mlir/Dialect/SCF/Transforms/Patterns.h @@ -68,8 +68,7 @@ void populateSCFStructuralTypeConversionTarget( /// applyPartialOneToNConversion. /// FIXME: The 1:N dialect conversion is deprecated and will be removed soon. /// 1:N support has been added to the regular dialect conversion driver. -LLVM_DEPRECATED("Use populateSCFStructuralTypeConversions() instead", - "populateSCFStructuralTypeConversions") +/// Use populateSCFStructuralTypeConversions() instead. void populateSCFStructuralOneToNTypeConversions( const TypeConverter &typeConverter, RewritePatternSet &patterns); diff --git a/mlir/include/mlir/Transforms/OneToNTypeConversion.h b/mlir/include/mlir/Transforms/OneToNTypeConversion.h index 9c74bf916d971..37a326818d645 100644 --- a/mlir/include/mlir/Transforms/OneToNTypeConversion.h +++ b/mlir/include/mlir/Transforms/OneToNTypeConversion.h @@ -123,9 +123,7 @@ class OneToNPatternRewriter : public PatternRewriter { /// (i.e., the converted types must be the same as the types of the new /// values). /// FIXME: The 1:N dialect conversion is deprecated and will be removed soon. - /// 1:N support has been added to the regular dialect conversion driver. - LLVM_DEPRECATED("Use replaceOpWithMultiple() instead", - "replaceOpWithMultiple") + /// Use replaceOpWithMultiple() instead. void replaceOp(Operation *op, ValueRange newValues, const OneToNTypeMapping &resultMapping); using PatternRewriter::replaceOp; @@ -260,8 +258,7 @@ class OneToNOpConversionPattern : public OneToNConversionPattern { /// only "partial"). /// FIXME: The 1:N dialect conversion is deprecated and will be removed soon. /// 1:N support has been added to the regular dialect conversion driver. -LLVM_DEPRECATED("Use applyPartialConversion() instead", - "applyPartialConversion") +/// Use applyPartialConversion() instead. LogicalResult applyPartialOneToNConversion(Operation *op, TypeConverter &typeConverter, const FrozenRewritePatternSet &patterns); @@ -272,9 +269,7 @@ applyPartialOneToNConversion(Operation *op, TypeConverter &typeConverter, /// used with the 1:N dialect conversion. /// FIXME: The 1:N dialect conversion is deprecated and will be removed soon. /// 1:N support has been added to the regular dialect conversion driver. -LLVM_DEPRECATED( - "Use populateFunctionOpInterfaceTypeConversionPattern() instead", - "populateFunctionOpInterfaceTypeConversionPattern") +/// Use populateFunctionOpInterfaceTypeConversionPattern() instead. void populateOneToNFunctionOpInterfaceTypeConversionPattern( StringRef functionLikeOpName, const TypeConverter &converter, RewritePatternSet &patterns); From f69585235ec85d54e0f3fc41b2d5700430907f99 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 8 Jan 2025 17:12:59 +0100 Subject: [PATCH 036/163] [libc++] Put _LIBCPP_NODEBUG on all internal aliases (#118710) This significantly reduces the amount of debug information generated for codebases using libc++, without hurting the debugging experience. --- libcxx/include/__algorithm/comp_ref_type.h | 4 +- libcxx/include/__algorithm/copy.h | 2 +- .../include/__algorithm/iterator_operations.h | 18 +++---- libcxx/include/__algorithm/move.h | 2 +- .../__algorithm/ranges_iterator_concept.h | 2 +- .../include/__algorithm/ranges_unique_copy.h | 2 +- libcxx/include/__algorithm/simd_utils.h | 6 +-- libcxx/include/__algorithm/sort.h | 4 +- .../__algorithm/three_way_comp_ref_type.h | 4 +- libcxx/include/__algorithm/unwrap_iter.h | 2 +- libcxx/include/__atomic/aliases.h | 10 ++-- libcxx/include/__atomic/atomic.h | 20 ++++---- libcxx/include/__atomic/atomic_ref.h | 10 ++-- libcxx/include/__atomic/atomic_sync.h | 2 +- libcxx/include/__atomic/contention_t.h | 6 +-- libcxx/include/__atomic/memory_order.h | 2 +- libcxx/include/__bit_reference | 24 ++++----- libcxx/include/__chrono/formatter.h | 46 ++++++++--------- libcxx/include/__chrono/hh_mm_ss.h | 2 +- .../include/__chrono/parser_std_format_spec.h | 2 +- libcxx/include/__chrono/zoned_time.h | 4 +- libcxx/include/__compare/ordering.h | 4 +- libcxx/include/__compare/synth_three_way.h | 3 +- libcxx/include/__exception/exception_ptr.h | 2 +- libcxx/include/__expected/expected.h | 10 ++-- libcxx/include/__expected/unexpected.h | 12 ++--- libcxx/include/__filesystem/path.h | 34 ++++++------- libcxx/include/__flat_map/flat_map.h | 2 +- .../include/__flat_map/key_value_iterator.h | 6 +-- libcxx/include/__format/buffer.h | 16 +++--- libcxx/include/__format/concepts.h | 2 +- libcxx/include/__format/container_adaptor.h | 4 +- libcxx/include/__format/format_arg.h | 2 +- libcxx/include/__format/format_arg_store.h | 2 +- libcxx/include/__format/format_functions.h | 2 +- .../__format/formatter_floating_point.h | 2 +- libcxx/include/__format/formatter_string.h | 10 ++-- .../__format/range_default_formatter.h | 12 ++--- libcxx/include/__format/unicode.h | 12 ++--- libcxx/include/__functional/binary_function.h | 4 +- libcxx/include/__functional/bind.h | 2 +- .../__functional/boyer_moore_searcher.h | 4 +- libcxx/include/__functional/function.h | 4 +- libcxx/include/__functional/perfect_forward.h | 2 +- libcxx/include/__functional/unary_function.h | 4 +- libcxx/include/__hash_table | 4 +- libcxx/include/__iterator/aliasing_iterator.h | 6 +-- libcxx/include/__iterator/concepts.h | 8 +-- libcxx/include/__iterator/insert_iterator.h | 4 +- libcxx/include/__iterator/iterator_traits.h | 51 ++++++++++--------- libcxx/include/__iterator/projected.h | 12 ++--- .../__iterator/ranges_iterator_traits.h | 6 +-- libcxx/include/__iterator/reverse_iterator.h | 4 +- .../include/__iterator/segmented_iterator.h | 2 +- libcxx/include/__locale | 2 +- libcxx/include/__locale_dir/locale_base_api.h | 2 +- libcxx/include/__mdspan/extents.h | 9 ++-- libcxx/include/__memory/allocation_guard.h | 4 +- libcxx/include/__memory/pointer_traits.h | 8 +-- libcxx/include/__memory/shared_ptr.h | 9 ++-- libcxx/include/__memory/unique_ptr.h | 10 ++-- .../__memory/unique_temporary_buffer.h | 2 +- libcxx/include/__node_handle | 4 +- libcxx/include/__pstl/backend_fwd.h | 8 +-- libcxx/include/__pstl/dispatch.h | 3 +- libcxx/include/__ranges/chunk_by_view.h | 2 +- libcxx/include/__ranges/drop_view.h | 4 +- libcxx/include/__ranges/drop_while_view.h | 2 +- libcxx/include/__ranges/elements_view.h | 4 +- libcxx/include/__ranges/filter_view.h | 4 +- libcxx/include/__ranges/iota_view.h | 2 +- libcxx/include/__ranges/join_view.h | 31 +++++------ libcxx/include/__ranges/lazy_split_view.h | 11 ++-- libcxx/include/__ranges/repeat_view.h | 4 +- libcxx/include/__ranges/reverse_view.h | 3 +- libcxx/include/__ranges/split_view.h | 2 +- libcxx/include/__ranges/subrange.h | 2 +- libcxx/include/__ranges/take_view.h | 6 +-- libcxx/include/__ranges/take_while_view.h | 2 +- libcxx/include/__ranges/transform_view.h | 10 ++-- libcxx/include/__split_buffer | 26 +++++----- libcxx/include/__stop_token/stop_state.h | 8 +-- libcxx/include/__thread/support/pthread.h | 2 +- libcxx/include/__tuple/make_tuple_types.h | 10 ++-- libcxx/include/__tuple/sfinae_helpers.h | 2 +- libcxx/include/__tuple/tuple_size.h | 2 +- .../__type_traits/add_lvalue_reference.h | 2 +- libcxx/include/__type_traits/add_pointer.h | 2 +- .../__type_traits/add_rvalue_reference.h | 2 +- .../include/__type_traits/aligned_storage.h | 2 +- .../include/__type_traits/common_reference.h | 20 ++++---- libcxx/include/__type_traits/common_type.h | 4 +- libcxx/include/__type_traits/conjunction.h | 2 +- libcxx/include/__type_traits/copy_cv.h | 10 ++-- libcxx/include/__type_traits/copy_cvref.h | 2 +- libcxx/include/__type_traits/disjunction.h | 2 +- libcxx/include/__type_traits/invoke.h | 21 ++++---- .../__type_traits/is_always_bitcastable.h | 4 +- .../include/__type_traits/is_char_like_type.h | 2 +- .../__type_traits/is_equality_comparable.h | 2 +- .../__type_traits/is_execution_policy.h | 2 +- .../__type_traits/is_primary_template.h | 5 +- libcxx/include/__type_traits/is_same.h | 4 +- libcxx/include/__type_traits/is_swappable.h | 5 +- .../__type_traits/make_32_64_or_128_bit.h | 2 +- .../__type_traits/make_const_lvalue_ref.h | 2 +- libcxx/include/__type_traits/make_signed.h | 2 +- libcxx/include/__type_traits/make_unsigned.h | 4 +- libcxx/include/__type_traits/maybe_const.h | 2 +- .../__type_traits/remove_all_extents.h | 2 +- libcxx/include/__type_traits/remove_const.h | 2 +- .../include/__type_traits/remove_const_ref.h | 2 +- libcxx/include/__type_traits/remove_cv.h | 4 +- libcxx/include/__type_traits/remove_cvref.h | 2 +- libcxx/include/__type_traits/remove_extent.h | 2 +- libcxx/include/__type_traits/remove_pointer.h | 4 +- .../include/__type_traits/remove_reference.h | 2 +- .../include/__type_traits/remove_volatile.h | 2 +- libcxx/include/__type_traits/void_t.h | 2 +- libcxx/include/__utility/exception_guard.h | 4 +- libcxx/include/__utility/forward_like.h | 6 +-- libcxx/include/__utility/in_place.h | 4 +- libcxx/include/__utility/integer_sequence.h | 8 +-- libcxx/include/__utility/move.h | 2 +- libcxx/include/__utility/pair.h | 2 +- libcxx/include/__utility/swap.h | 5 +- libcxx/include/__vector/vector.h | 2 +- libcxx/include/any | 11 ++-- libcxx/include/array | 29 ++++++----- libcxx/include/barrier | 2 +- libcxx/include/ccomplex | 9 ++-- libcxx/include/ciso646 | 5 +- libcxx/include/complex | 2 +- libcxx/include/cstdalign | 8 +-- libcxx/include/cstdbool | 8 +-- libcxx/include/ctgmath | 9 ++-- libcxx/include/deque | 29 ++++++----- libcxx/include/experimental/__simd/scalar.h | 6 +-- libcxx/include/experimental/__simd/simd.h | 4 +- .../include/experimental/__simd/simd_mask.h | 4 +- libcxx/include/experimental/__simd/vec_ext.h | 6 +-- libcxx/include/forward_list | 3 +- libcxx/include/ios | 4 +- libcxx/include/optional | 27 +++++----- libcxx/include/ratio | 2 +- libcxx/include/regex | 3 +- libcxx/include/source_location | 2 +- libcxx/include/string | 4 +- libcxx/include/tuple | 3 +- libcxx/include/variant | 34 ++++++------- .../tools/clang_tidy_checks/CMakeLists.txt | 1 + .../tools/clang_tidy_checks/libcpp_module.cpp | 2 + .../clang_tidy_checks/nodebug_on_aliases.cpp | 35 +++++++++++++ .../clang_tidy_checks/nodebug_on_aliases.hpp | 18 +++++++ .../clang_tidy_checks/uglify_attributes.cpp | 21 ++------ .../tools/clang_tidy_checks/utilities.hpp | 22 ++++++++ 156 files changed, 599 insertions(+), 504 deletions(-) create mode 100644 libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.cpp create mode 100644 libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.hpp create mode 100644 libcxx/test/tools/clang_tidy_checks/utilities.hpp diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h index c367fbb91ac28..6a9d5cef26719 100644 --- a/libcxx/include/__algorithm/comp_ref_type.h +++ b/libcxx/include/__algorithm/comp_ref_type.h @@ -56,10 +56,10 @@ struct __debug_less { // Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference. #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG template -using __comp_ref_type = __debug_less<_Comp>; +using __comp_ref_type _LIBCPP_NODEBUG = __debug_less<_Comp>; #else template -using __comp_ref_type = _Comp&; +using __comp_ref_type _LIBCPP_NODEBUG = _Comp&; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 4f30b2050abba..962aa90059d57 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -47,7 +47,7 @@ struct __copy_impl { template struct _CopySegment { - using _Traits = __segmented_iterator_traits<_InIter>; + using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>; _OutIter& __result_; diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 6cdb0aec9b2db..e5c89c1e67e3a 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -48,13 +48,13 @@ struct _RangeAlgPolicy {}; template <> struct _IterOps<_RangeAlgPolicy> { template - using __value_type = iter_value_t<_Iter>; + using __value_type _LIBCPP_NODEBUG = iter_value_t<_Iter>; template - using __iterator_category = ranges::__iterator_concept<_Iter>; + using __iterator_category _LIBCPP_NODEBUG = ranges::__iterator_concept<_Iter>; template - using __difference_type = iter_difference_t<_Iter>; + using __difference_type _LIBCPP_NODEBUG = iter_difference_t<_Iter>; static constexpr auto advance = ranges::advance; static constexpr auto distance = ranges::distance; @@ -72,13 +72,13 @@ struct _ClassicAlgPolicy {}; template <> struct _IterOps<_ClassicAlgPolicy> { template - using __value_type = typename iterator_traits<_Iter>::value_type; + using __value_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type; template - using __iterator_category = typename iterator_traits<_Iter>::iterator_category; + using __iterator_category _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; template - using __difference_type = typename iterator_traits<_Iter>::difference_type; + using __difference_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type; // advance template @@ -94,10 +94,10 @@ struct _IterOps<_ClassicAlgPolicy> { } template - using __deref_t = decltype(*std::declval<_Iter&>()); + using __deref_t _LIBCPP_NODEBUG = decltype(*std::declval<_Iter&>()); template - using __move_t = decltype(std::move(*std::declval<_Iter&>())); + using __move_t _LIBCPP_NODEBUG = decltype(std::move(*std::declval<_Iter&>())); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void __validate_iter_reference() { @@ -217,7 +217,7 @@ struct _IterOps<_ClassicAlgPolicy> { }; template -using __policy_iter_diff_t = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>; +using __policy_iter_diff_t _LIBCPP_NODEBUG = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index 005099dcac06e..6f3b0eb5d2927 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -50,7 +50,7 @@ struct __move_impl { template struct _MoveSegment { - using _Traits = __segmented_iterator_traits<_InIter>; + using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>; _OutIter& __result_; diff --git a/libcxx/include/__algorithm/ranges_iterator_concept.h b/libcxx/include/__algorithm/ranges_iterator_concept.h index 2af891d3af005..58790e95aa803 100644 --- a/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -44,7 +44,7 @@ consteval auto __get_iterator_concept() { } template -using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); +using __iterator_concept _LIBCPP_NODEBUG = decltype(__get_iterator_concept<_Iter>()); } // namespace ranges _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h index 3b4a64e94ca1f..ee7f0a0187b73 100644 --- a/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/libcxx/include/__algorithm/ranges_unique_copy.h @@ -60,7 +60,7 @@ struct __unique_copy { } template - using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>()); + using __algo_tag_t _LIBCPP_NODEBUG = decltype(__get_algo_tag<_InIter, _OutIter>()); template _Sent, diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h index 3ca79247bbd03..822fca1d32bf8 100644 --- a/libcxx/include/__algorithm/simd_utils.h +++ b/libcxx/include/__algorithm/simd_utils.h @@ -70,7 +70,7 @@ struct __get_as_integer_type_impl<8> { }; template -using __get_as_integer_type_t = typename __get_as_integer_type_impl::type; +using __get_as_integer_type_t _LIBCPP_NODEBUG = typename __get_as_integer_type_impl::type; // This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance // in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms @@ -90,7 +90,7 @@ inline constexpr size_t __native_vector_size = 1; # endif template -using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT; +using __simd_vector __attribute__((__ext_vector_type__(_Np))) _LIBCPP_NODEBUG = _ArithmeticT; template inline constexpr size_t __simd_vector_size_v = []() -> size_t { @@ -106,7 +106,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, } template -using __simd_vector_underlying_type_t = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); +using __simd_vector_underlying_type_t _LIBCPP_NODEBUG = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); // This isn't inlined without always_inline when loading chars. template diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h index ed828b6d72314..5c60b23931cca 100644 --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -890,10 +890,10 @@ __sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co } template -using __is_any_of = _Or...>; +using __is_any_of _LIBCPP_NODEBUG = _Or...>; template -using __sort_is_specialized_in_library = __is_any_of< +using __sort_is_specialized_in_library _LIBCPP_NODEBUG = __is_any_of< _Type, char, #if _LIBCPP_HAS_WIDE_CHARACTERS diff --git a/libcxx/include/__algorithm/three_way_comp_ref_type.h b/libcxx/include/__algorithm/three_way_comp_ref_type.h index 5702a1fee0826..f6f76455e4664 100644 --- a/libcxx/include/__algorithm/three_way_comp_ref_type.h +++ b/libcxx/include/__algorithm/three_way_comp_ref_type.h @@ -61,10 +61,10 @@ struct __debug_three_way_comp { // Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference. # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG template -using __three_way_comp_ref_type = __debug_three_way_comp<_Comp>; +using __three_way_comp_ref_type _LIBCPP_NODEBUG = __debug_three_way_comp<_Comp>; # else template -using __three_way_comp_ref_type = _Comp&; +using __three_way_comp_ref_type _LIBCPP_NODEBUG = _Comp&; # endif #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h index 8cc0d22d4fc21..b66a682e765fa 100644 --- a/libcxx/include/__algorithm/unwrap_iter.h +++ b/libcxx/include/__algorithm/unwrap_iter.h @@ -46,7 +46,7 @@ struct __unwrap_iter_impl { // It's a contiguous iterator, so we can use a raw pointer instead template struct __unwrap_iter_impl<_Iter, true> { - using _ToAddressT = decltype(std::__to_address(std::declval<_Iter>())); + using _ToAddressT _LIBCPP_NODEBUG = decltype(std::__to_address(std::declval<_Iter>())); static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter __orig_iter, _ToAddressT __unwrapped_iter) { return __orig_iter + (__unwrapped_iter - std::__to_address(__orig_iter)); diff --git a/libcxx/include/__atomic/aliases.h b/libcxx/include/__atomic/aliases.h index 37d11dd0aabf3..4fccebab25636 100644 --- a/libcxx/include/__atomic/aliases.h +++ b/libcxx/include/__atomic/aliases.h @@ -84,19 +84,19 @@ using atomic_uintmax_t = atomic; // C++20 atomic_{signed,unsigned}_lock_free: prefer the contention type most highly, then the largest lock-free type #if _LIBCPP_STD_VER >= 20 # if ATOMIC_LLONG_LOCK_FREE == 2 -using __largest_lock_free_type = long long; +using __largest_lock_free_type _LIBCPP_NODEBUG = long long; # elif ATOMIC_INT_LOCK_FREE == 2 -using __largest_lock_free_type = int; +using __largest_lock_free_type _LIBCPP_NODEBUG = int; # elif ATOMIC_SHORT_LOCK_FREE == 2 -using __largest_lock_free_type = short; +using __largest_lock_free_type _LIBCPP_NODEBUG = short; # elif ATOMIC_CHAR_LOCK_FREE == 2 -using __largest_lock_free_type = char; +using __largest_lock_free_type _LIBCPP_NODEBUG = char; # else # define _LIBCPP_NO_LOCK_FREE_TYPES // There are no lockfree types (this can happen on unusual platforms) # endif # ifndef _LIBCPP_NO_LOCK_FREE_TYPES -using __contention_t_or_largest = +using __contention_t_or_largest _LIBCPP_NODEBUG = __conditional_t<__libcpp_is_always_lock_free<__cxx_contention_t>::__value, __cxx_contention_t, __largest_lock_free_type>; diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 8029b52770d26..975a479e20400 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -143,7 +143,7 @@ struct __atomic_base // false template struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { - using __base = __atomic_base<_Tp, false>; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default; @@ -228,9 +228,9 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { template struct atomic : public __atomic_base<_Tp> { - using __base = __atomic_base<_Tp>; - using value_type = _Tp; - using difference_type = value_type; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI atomic() = default; @@ -257,9 +257,9 @@ struct atomic : public __atomic_base<_Tp> { template struct atomic<_Tp*> : public __atomic_base<_Tp*> { - using __base = __atomic_base<_Tp*>; - using value_type = _Tp*; - using difference_type = ptrdiff_t; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>; + using value_type = _Tp*; + using difference_type = ptrdiff_t; _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default; @@ -389,9 +389,9 @@ struct atomic<_Tp> : __atomic_base<_Tp> { } public: - using __base = __atomic_base<_Tp>; - using value_type = _Tp; - using difference_type = value_type; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default; _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {} diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index eef15983b9833..177ea646b6cd0 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -221,7 +221,7 @@ struct __atomic_ref_base { _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } protected: - using _Aligned_Tp [[__gnu__::__aligned__(required_alignment)]] = _Tp; + using _Aligned_Tp [[__gnu__::__aligned__(required_alignment), __gnu__::__nodebug__]] = _Tp; _Aligned_Tp* __ptr_; _LIBCPP_HIDE_FROM_ABI __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} @@ -241,7 +241,7 @@ template struct atomic_ref : public __atomic_ref_base<_Tp> { static_assert(is_trivially_copyable_v<_Tp>, "std::atomic_ref requires that 'T' be a trivially copyable type"); - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( @@ -259,7 +259,7 @@ struct atomic_ref : public __atomic_ref_base<_Tp> { template requires(std::integral<_Tp> && !std::same_as) struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; using difference_type = __base::value_type; @@ -305,7 +305,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { template requires std::floating_point<_Tp> struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; using difference_type = __base::value_type; @@ -344,7 +344,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { template struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> { - using __base = __atomic_ref_base<_Tp*>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp*>; using difference_type = ptrdiff_t; diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h index 153001e7b62e3..ab9bc59fdcfe7 100644 --- a/libcxx/include/__atomic/atomic_sync.h +++ b/libcxx/include/__atomic/atomic_sync.h @@ -81,7 +81,7 @@ struct __atomic_wait_backoff_impl { _Poll __poll_; memory_order __order_; - using __waitable_traits = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >; + using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool diff --git a/libcxx/include/__atomic/contention_t.h b/libcxx/include/__atomic/contention_t.h index 6f2a073bc1a8e..5b42a0125f875 100644 --- a/libcxx/include/__atomic/contention_t.h +++ b/libcxx/include/__atomic/contention_t.h @@ -20,12 +20,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) -using __cxx_contention_t = int32_t; +using __cxx_contention_t _LIBCPP_NODEBUG = int32_t; #else -using __cxx_contention_t = int64_t; +using __cxx_contention_t _LIBCPP_NODEBUG = int64_t; #endif // __linux__ || (_AIX && !__64BIT__) -using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; +using __cxx_atomic_contention_t _LIBCPP_NODEBUG = __cxx_atomic_impl<__cxx_contention_t>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__atomic/memory_order.h b/libcxx/include/__atomic/memory_order.h index 294121d1c4e7f..44790fe888b36 100644 --- a/libcxx/include/__atomic/memory_order.h +++ b/libcxx/include/__atomic/memory_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // to pin the underlying type in C++20. enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst }; -using __memory_order_underlying_t = underlying_type<__legacy_memory_order>::type; +using __memory_order_underlying_t _LIBCPP_NODEBUG = underlying_type<__legacy_memory_order>::type; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 9fa24c98d493f..7e27090cc68a4 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -43,8 +43,8 @@ struct __has_storage_type { template ::value> class __bit_reference { - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__storage_pointer; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__storage_pointer; __storage_pointer __seg_; __storage_type __mask_; @@ -55,7 +55,7 @@ class __bit_reference { friend class __bit_iterator<_Cp, false>; public: - using __container = typename _Cp::__self; + using __container _LIBCPP_NODEBUG = typename _Cp::__self; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default; @@ -135,8 +135,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, template class __bit_const_reference { - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__const_storage_pointer; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__const_storage_pointer; __storage_pointer __seg_; __storage_type __mask_; @@ -145,7 +145,7 @@ class __bit_const_reference { friend class __bit_iterator<_Cp, true>; public: - using __container = typename _Cp::__self; + using __container _LIBCPP_NODEBUG = typename _Cp::__self; _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default; __bit_const_reference& operator=(const __bit_const_reference&) = delete; @@ -587,10 +587,10 @@ inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges( template struct __bit_array { - using difference_type = typename _Cp::difference_type; - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__storage_pointer; - using iterator = typename _Cp::iterator; + using difference_type _LIBCPP_NODEBUG = typename _Cp::difference_type; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__storage_pointer; + using iterator _LIBCPP_NODEBUG = typename _Cp::iterator; static const unsigned __bits_per_word = _Cp::__bits_per_word; static const unsigned _Np = 4; @@ -790,8 +790,8 @@ public: using iterator_category = random_access_iterator_tag; private: - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer>; static const unsigned __bits_per_word = _Cp::__bits_per_word; diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 3671e6aa52b49..1086dde381955 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -711,7 +711,7 @@ struct _LIBCPP_TEMPLATE_VIS __formatter_chrono { template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -722,7 +722,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : pub template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -733,7 +733,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : pu template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -745,7 +745,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : p template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -767,7 +767,7 @@ struct formatter, _CharT> : public __formatter_c template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -778,7 +778,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -789,7 +789,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatte template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -800,7 +800,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -811,7 +811,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __format template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -822,7 +822,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -833,7 +833,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __f template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -844,7 +844,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __form template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -855,7 +855,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public _ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -866,7 +866,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -877,7 +877,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : publ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -888,7 +888,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __for template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -899,7 +899,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public _ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -910,7 +910,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : pub template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -921,7 +921,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : publ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -932,7 +932,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -944,7 +944,7 @@ struct formatter, _CharT> : public __formatter_chron template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -955,7 +955,7 @@ struct formatter : public __formatter_chrono<_CharT> { template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -968,7 +968,7 @@ struct formatter : public __formatter_chrono<_CharT> template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { diff --git a/libcxx/include/__chrono/hh_mm_ss.h b/libcxx/include/__chrono/hh_mm_ss.h index c460b11305085..6ea8a28ee0938 100644 --- a/libcxx/include/__chrono/hh_mm_ss.h +++ b/libcxx/include/__chrono/hh_mm_ss.h @@ -30,7 +30,7 @@ template class hh_mm_ss { private: static_assert(__is_duration_v<_Duration>, "template parameter of hh_mm_ss must be a std::chrono::duration"); - using __CommonType = common_type_t<_Duration, chrono::seconds>; + using __CommonType _LIBCPP_NODEBUG = common_type_t<_Duration, chrono::seconds>; _LIBCPP_HIDE_FROM_ABI static constexpr uint64_t __pow10(unsigned __exp) { uint64_t __ret = 1; diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h index 3976864c12b98..4df8e603c6bcf 100644 --- a/libcxx/include/__chrono/parser_std_format_spec.h +++ b/libcxx/include/__chrono/parser_std_format_spec.h @@ -140,7 +140,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { template class _LIBCPP_TEMPLATE_VIS __parser_chrono { - using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator; + using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator; public: template diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index f57e65c90a624..1deba10d96ae8 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -66,7 +66,7 @@ class zoned_time { // Using these constraints in the code causes the compiler to give an // error that the constraint depends on itself. To avoid that issue use // the fact it is possible to create this object from a _TimeZonePtr. - using __traits = zoned_traits<_TimeZonePtr>; + using __traits _LIBCPP_NODEBUG = zoned_traits<_TimeZonePtr>; public: using duration = common_type_t<_Duration, seconds>; @@ -186,7 +186,7 @@ template zoned_time(sys_time<_Duration>) -> zoned_time>; template -using __time_zone_representation = +using __time_zone_representation _LIBCPP_NODEBUG = conditional_t, const time_zone*, remove_cvref_t<_TimeZonePtrOrName>>; diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h index 297218e6f29e5..902ef5329dd43 100644 --- a/libcxx/include/__compare/ordering.h +++ b/libcxx/include/__compare/ordering.h @@ -120,7 +120,7 @@ inline constexpr partial_ordering partial_ordering::greater(_PartialOrdResult::_ inline constexpr partial_ordering partial_ordering::unordered(_PartialOrdResult::__unordered); class weak_ordering { - using _ValueT = signed char; + using _ValueT _LIBCPP_NODEBUG = signed char; _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} @@ -190,7 +190,7 @@ inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); class strong_ordering { - using _ValueT = signed char; + using _ValueT _LIBCPP_NODEBUG = signed char; _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} diff --git a/libcxx/include/__compare/synth_three_way.h b/libcxx/include/__compare/synth_three_way.h index e48ce49799836..63bf56d0cf42b 100644 --- a/libcxx/include/__compare/synth_three_way.h +++ b/libcxx/include/__compare/synth_three_way.h @@ -43,7 +43,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = [] -using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); +using __synth_three_way_result _LIBCPP_NODEBUG = + decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 7df46a0e94dce..6257e6f729bf3 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -66,7 +66,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { public: // exception_ptr is basically a COW string. - using __trivially_relocatable = exception_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr; _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index 3d3f11967ee74..03bbd1623ed5c 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -459,14 +459,14 @@ class expected : private __expected_base<_Tp, _Err> { template friend class expected; - using __base = __expected_base<_Tp, _Err>; + using __base _LIBCPP_NODEBUG = __expected_base<_Tp, _Err>; public: using value_type = _Tp; using error_type = _Err; using unexpected_type = unexpected<_Err>; - using __trivially_relocatable = + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value, expected, void>; @@ -505,7 +505,7 @@ class expected : private __expected_base<_Tp, _Err> { private: template - using __can_convert = _And< + using __can_convert _LIBCPP_NODEBUG = _And< is_constructible<_Tp, _UfQual>, is_constructible<_Err, _OtherErrQual>, _If<_Not, bool>>::value, @@ -1363,7 +1363,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { friend class expected; template - using __can_convert = + using __can_convert _LIBCPP_NODEBUG = _And< is_void<_Up>, is_constructible<_Err, _OtherErrQual>, _Not, expected<_Up, _OtherErr>&>>, @@ -1371,7 +1371,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { _Not, const expected<_Up, _OtherErr>&>>, _Not, const expected<_Up, _OtherErr>>>>; - using __base = __expected_void_base<_Err>; + using __base _LIBCPP_NODEBUG = __expected_void_base<_Err>; public: using value_type = _Tp; diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h index cf110bcf69a82..6904889b8c6b1 100644 --- a/libcxx/include/__expected/unexpected.h +++ b/libcxx/include/__expected/unexpected.h @@ -48,12 +48,12 @@ template struct __is_std_unexpected> : true_type {}; template -using __valid_std_unexpected = _BoolConstant< // - is_object_v<_Tp> && // - !is_array_v<_Tp> && // - !__is_std_unexpected<_Tp>::value && // - !is_const_v<_Tp> && // - !is_volatile_v<_Tp> // +using __valid_std_unexpected _LIBCPP_NODEBUG = _BoolConstant< // + is_object_v<_Tp> && // + !is_array_v<_Tp> && // + !__is_std_unexpected<_Tp>::value && // + !is_const_v<_Tp> && // + !is_volatile_v<_Tp> // >; template diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 509d1cc8052f0..0a751ba32954f 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -51,30 +51,30 @@ template struct __can_convert_char : public __can_convert_char<_Tp> {}; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char; }; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = wchar_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = wchar_t; }; # if _LIBCPP_HAS_CHAR8_T template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char8_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char8_t; }; # endif template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char16_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char16_t; }; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char32_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char32_t; }; template ::value, int> = 0> @@ -95,7 +95,7 @@ typedef string __u8_string; struct _NullSentinel {}; template -using _Void = void; +using _Void _LIBCPP_NODEBUG = void; template struct __is_pathable_string : public false_type {}; @@ -104,7 +104,7 @@ template struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>, _Void::__char_type> > : public __can_convert_char<_ECharT> { - using _Str = basic_string<_ECharT, _Traits, _Alloc>; + using _Str _LIBCPP_NODEBUG = basic_string<_ECharT, _Traits, _Alloc>; _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } @@ -117,7 +117,7 @@ template struct __is_pathable_string< basic_string_view<_ECharT, _Traits>, _Void::__char_type> > : public __can_convert_char<_ECharT> { - using _Str = basic_string_view<_ECharT, _Traits>; + using _Str _LIBCPP_NODEBUG = basic_string_view<_ECharT, _Traits>; _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } @@ -157,7 +157,7 @@ struct __is_pathable_iter< true, _Void::value_type>::__char_type> > : __can_convert_char::value_type> { - using _ECharT = typename iterator_traits<_Iter>::value_type; + using _ECharT _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type; _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; } @@ -380,13 +380,13 @@ struct _PathExport { class _LIBCPP_EXPORTED_FROM_ABI path { template - using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>; + using _EnableIfPathable _LIBCPP_NODEBUG = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>; template - using _SourceChar = typename __is_pathable<_Tp>::__char_type; + using _SourceChar _LIBCPP_NODEBUG = typename __is_pathable<_Tp>::__char_type; template - using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; + using _SourceCVT _LIBCPP_NODEBUG = _PathCVT<_SourceChar<_Tp> >; public: # if defined(_LIBCPP_WIN32API) diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index b66bc1cb66fc1..9fe84250b1204 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -90,7 +90,7 @@ class flat_map { static_assert(!is_same_v<_MappedContainer, std::vector>, "vector is not a sequence container"); template - using __iterator = __key_value_iterator; + using __iterator _LIBCPP_NODEBUG = __key_value_iterator; public: // types diff --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h index 987ac677a4130..06a23f3429974 100644 --- a/libcxx/include/__flat_map/key_value_iterator.h +++ b/libcxx/include/__flat_map/key_value_iterator.h @@ -41,9 +41,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __key_value_iterator { private: - using __key_iterator = ranges::iterator_t; - using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>; - using __reference = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>; + using __key_iterator _LIBCPP_NODEBUG = ranges::iterator_t; + using __mapped_iterator _LIBCPP_NODEBUG = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>; + using __reference _LIBCPP_NODEBUG = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>; struct __arrow_proxy { __reference __ref_; diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h index 618b8ef025643..9509f19e16724 100644 --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -322,7 +322,7 @@ struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container class _LIBCPP_TEMPLATE_VIS __writer_container { public: - using _CharT = typename _Container::value_type; + using _CharT _LIBCPP_NODEBUG = typename _Container::value_type; _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it) : __container_{__out_it.__get_container()} {} @@ -340,7 +340,7 @@ class _LIBCPP_TEMPLATE_VIS __writer_container { /// Selects the type of the writer used for the output iterator. template class _LIBCPP_TEMPLATE_VIS __writer_selector { - using _Container = typename __back_insert_iterator_container<_OutIt>::type; + using _Container _LIBCPP_NODEBUG = typename __back_insert_iterator_container<_OutIt>::type; public: using type = @@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __writer_selector { template requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS __format_buffer { - using _Storage = + using _Storage _LIBCPP_NODEBUG = conditional_t<__enable_direct_output<_OutIt, _CharT>, __direct_storage<_CharT>, __internal_storage<_CharT>>; public: @@ -408,7 +408,7 @@ class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { template requires(output_iterator<_OutIt, const _CharT&>) struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { - using _Size = iter_difference_t<_OutIt>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) @@ -438,7 +438,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { template requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> { - using _Size = iter_difference_t<_OutIt>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) @@ -489,8 +489,8 @@ template requires(output_iterator<_OutIt, const _CharT&>) struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> { - using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; - using _Size = iter_difference_t<_OutIt>; + using _Base _LIBCPP_NODEBUG = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size) @@ -523,7 +523,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final // would lead to a circular include with formatter for vector. template <__fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __retarget_buffer { - using _Alloc = allocator<_CharT>; + using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; public: using value_type = _CharT; diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index 2c40e3e314917..28297c612db77 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -44,7 +44,7 @@ concept __fmt_char_type = // (Note testing for (w)format_context would be a valid choice, but requires // selecting the proper one depending on the type of _CharT.) template -using __fmt_iter_for = _CharT*; +using __fmt_iter_for _LIBCPP_NODEBUG = _CharT*; template >> concept __formattable_with = diff --git a/libcxx/include/__format/container_adaptor.h b/libcxx/include/__format/container_adaptor.h index d3be2e1895604..48d42ee7d901b 100644 --- a/libcxx/include/__format/container_adaptor.h +++ b/libcxx/include/__format/container_adaptor.h @@ -37,8 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { private: - using __maybe_const_container = __fmt_maybe_const; - using __maybe_const_adaptor = __maybe_const, _Adaptor>; + using __maybe_const_container _LIBCPP_NODEBUG = __fmt_maybe_const; + using __maybe_const_adaptor _LIBCPP_NODEBUG = __maybe_const, _Adaptor>; formatter, _CharT> __underlying_; public: diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index a973ccd43c420..1c530fd5a5d03 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -208,7 +208,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< /// separate arrays. template class __basic_format_arg_value { - using _CharT = typename _Context::char_type; + using _CharT _LIBCPP_NODEBUG = typename _Context::char_type; public: /// Contains the implementation for basic_format_arg::handle. diff --git a/libcxx/include/__format/format_arg_store.h b/libcxx/include/__format/format_arg_store.h index 8b2c95c657c9b..4c5ee9e9e4fd3 100644 --- a/libcxx/include/__format/format_arg_store.h +++ b/libcxx/include/__format/format_arg_store.h @@ -257,7 +257,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { } } - using _Storage = + using _Storage _LIBCPP_NODEBUG = conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)), __format::__packed_format_arg_store<_Context, sizeof...(_Args)>, __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>; diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index 3991363c0124e..b920be5acbe86 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -379,7 +379,7 @@ struct _LIBCPP_TEMPLATE_VIS basic_format_string { private: basic_string_view<_CharT> __str_; - using _Context = __format::__compile_time_basic_format_context<_CharT>; + using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index e04fffb683c3a..ac4be9b619355 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -141,7 +141,7 @@ struct __traits { /// on the stack or the heap. template class _LIBCPP_TEMPLATE_VIS __float_buffer { - using _Traits = __traits<_Fp>; + using _Traits _LIBCPP_NODEBUG = __traits<_Fp>; public: // TODO FMT Improve this constructor to do a better estimate. diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h index 826d6421c8631..30084e582214d 100644 --- a/libcxx/include/__format/formatter_string.h +++ b/libcxx/include/__format/formatter_string.h @@ -59,7 +59,7 @@ struct _LIBCPP_TEMPLATE_VIS __formatter_string { // Formatter const char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { @@ -78,7 +78,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatte // Formatter char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter { - using _Base = formatter; + using _Base _LIBCPP_NODEBUG = formatter; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { @@ -89,7 +89,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -102,7 +102,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatte template <__fmt_char_type _CharT, class _Traits, class _Allocator> struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -115,7 +115,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, // Formatter std::string_view. template <__fmt_char_type _CharT, class _Traits> struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator diff --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h index fb21b0f8beb3a..bb4c520f5ea11 100644 --- a/libcxx/include/__format/range_default_formatter.h +++ b/libcxx/include/__format/range_default_formatter.h @@ -40,7 +40,7 @@ concept __const_formattable_range = ranges::input_range && formattable, _CharT>; template -using __fmt_maybe_const = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; +using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") @@ -95,7 +95,7 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; template struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; + using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; range_formatter>, _CharT> __underlying_; public: @@ -122,8 +122,8 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t>; + using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; range_formatter<__element_type, _CharT> __underlying_; public: @@ -150,8 +150,8 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t>; + using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; range_formatter<__element_type, _CharT> __underlying_; public: diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h index b4f22c739d6a1..46096fda1e8ae 100644 --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -123,7 +123,7 @@ class __code_point_view; /// UTF-8 specialization. template <> class __code_point_view { - using _Iterator = basic_string_view::const_iterator; + using _Iterator _LIBCPP_NODEBUG = basic_string_view::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) @@ -249,7 +249,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { /// - 4 UTF-32 (for example Linux) template <> class __code_point_view { - using _Iterator = typename basic_string_view::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view::const_iterator; public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); @@ -300,8 +300,8 @@ class __code_point_view { // This implements the extended rules see // https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries class __extended_grapheme_cluster_break { - using __EGC_property = __extended_grapheme_custer_property_boundary::__property; - using __inCB_property = __indic_conjunct_break::__property; + using __EGC_property _LIBCPP_NODEBUG = __extended_grapheme_custer_property_boundary::__property; + using __inCB_property _LIBCPP_NODEBUG = __indic_conjunct_break::__property; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_break(char32_t __first_code_point) @@ -527,7 +527,7 @@ class __extended_grapheme_cluster_break { /// Therefore only this code point is extracted. template class __extended_grapheme_cluster_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) @@ -572,7 +572,7 @@ __extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cl // This makes it easier to write code agnostic of the _LIBCPP_HAS_UNICODE define. template class __code_point_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) diff --git a/libcxx/include/__functional/binary_function.h b/libcxx/include/__functional/binary_function.h index ddee3b170311f..bde8b03ef8281 100644 --- a/libcxx/include/__functional/binary_function.h +++ b/libcxx/include/__functional/binary_function.h @@ -42,11 +42,11 @@ struct __binary_function_keep_layout_base { _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") template -using __binary_function = binary_function<_Arg1, _Arg2, _Result>; +using __binary_function _LIBCPP_NODEBUG = binary_function<_Arg1, _Arg2, _Result>; _LIBCPP_DIAGNOSTIC_POP #else template -using __binary_function = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; +using __binary_function _LIBCPP_NODEBUG = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h index f82c1517249b1..e31ad29790355 100644 --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -198,7 +198,7 @@ __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _ template class __bind : public __weak_result_type<__decay_t<_Fp> > { protected: - using _Fd = __decay_t<_Fp>; + using _Fd _LIBCPP_NODEBUG = __decay_t<_Fp>; typedef tuple<__decay_t<_BoundArgs>...> _Td; private: diff --git a/libcxx/include/__functional/boyer_moore_searcher.h b/libcxx/include/__functional/boyer_moore_searcher.h index 52a58d57a8d40..1e49cc5464be5 100644 --- a/libcxx/include/__functional/boyer_moore_searcher.h +++ b/libcxx/include/__functional/boyer_moore_searcher.h @@ -92,7 +92,7 @@ class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { private: using difference_type = typename std::iterator_traits<_RandomAccessIterator1>::difference_type; using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type; - using __skip_table_type = + using __skip_table_type _LIBCPP_NODEBUG = _BMSkipTable::difference_type; using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type; - using __skip_table_type = + using __skip_table_type _LIBCPP_NODEBUG = _BMSkipTable -using __fast_forward = __conditional_t::value, _Tp, _Tp&&>; +using __fast_forward _LIBCPP_NODEBUG = __conditional_t::value, _Tp, _Tp&&>; // __policy_invoker calls an instance of __alloc_func held in __policy_storage. @@ -847,7 +847,7 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> }; template - using _EnableIfLValueCallable = __enable_if_t<__callable<_Fp&>::value>; + using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<__callable<_Fp&>::value>; public: typedef _Rp result_type; diff --git a/libcxx/include/__functional/perfect_forward.h b/libcxx/include/__functional/perfect_forward.h index 8fd68db3d6eb8..37c3d15b4bec0 100644 --- a/libcxx/include/__functional/perfect_forward.h +++ b/libcxx/include/__functional/perfect_forward.h @@ -94,7 +94,7 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> { // __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require]. template -using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; +using __perfect_forward _LIBCPP_NODEBUG = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; #endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/__functional/unary_function.h b/libcxx/include/__functional/unary_function.h index 69b1bc94220ae..769ffc9893a72 100644 --- a/libcxx/include/__functional/unary_function.h +++ b/libcxx/include/__functional/unary_function.h @@ -39,11 +39,11 @@ struct __unary_function_keep_layout_base { _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") template -using __unary_function = unary_function<_Arg, _Result>; +using __unary_function _LIBCPP_NODEBUG = unary_function<_Arg, _Result>; _LIBCPP_DIAGNOSTIC_POP #else template -using __unary_function = __unary_function_keep_layout_base<_Arg, _Result>; +using __unary_function _LIBCPP_NODEBUG = __unary_function_keep_layout_base<_Arg, _Result>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 9c821ea690813..7788f687746f0 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -111,8 +111,8 @@ struct __hash_node_base { template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { typedef _Tp __node_value_type; - using _Base = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; - using __next_pointer = typename _Base::__next_pointer; + using _Base _LIBCPP_NODEBUG = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; + using __next_pointer _LIBCPP_NODEBUG = typename _Base::__next_pointer; size_t __hash_; diff --git a/libcxx/include/__iterator/aliasing_iterator.h b/libcxx/include/__iterator/aliasing_iterator.h index aeb5b4a88ec37..e01127142ae98 100644 --- a/libcxx/include/__iterator/aliasing_iterator.h +++ b/libcxx/include/__iterator/aliasing_iterator.h @@ -31,8 +31,8 @@ struct __aliasing_iterator_wrapper { class __iterator { _BaseIter __base_ = nullptr; - using __iter_traits = iterator_traits<_BaseIter>; - using __base_value_type = typename __iter_traits::value_type; + using __iter_traits _LIBCPP_NODEBUG = iterator_traits<_BaseIter>; + using __base_value_type _LIBCPP_NODEBUG = typename __iter_traits::value_type; static_assert(__has_random_access_iterator_category<_BaseIter>::value, "The base iterator has to be a random access iterator!"); @@ -120,7 +120,7 @@ struct __aliasing_iterator_wrapper { // This is required to avoid ADL instantiations on _BaseT template -using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; +using __aliasing_iterator _LIBCPP_NODEBUG = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h index 1c227933a482a..6e5ac1d3af37b 100644 --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -67,10 +67,10 @@ template concept indirectly_readable = __indirectly_readable_impl>; template -using __projected_iterator_t = typename _Tp::__projected_iterator; +using __projected_iterator_t _LIBCPP_NODEBUG = typename _Tp::__projected_iterator; template -using __projected_projection_t = typename _Tp::__projected_projection; +using __projected_projection_t _LIBCPP_NODEBUG = typename _Tp::__projected_projection; template concept __specialization_of_projected = requires { @@ -89,7 +89,7 @@ struct __indirect_value_t_impl<_Tp> { }; template -using __indirect_value_t = typename __indirect_value_t_impl<_Tp>::type; +using __indirect_value_t _LIBCPP_NODEBUG = typename __indirect_value_t_impl<_Tp>::type; template using iter_common_reference_t = common_reference_t, __indirect_value_t<_Tp>>; @@ -274,7 +274,7 @@ concept indirectly_copyable_storable = #endif // _LIBCPP_STD_VER >= 20 template -using __has_random_access_iterator_category_or_concept +using __has_random_access_iterator_category_or_concept _LIBCPP_NODEBUG #if _LIBCPP_STD_VER >= 20 = integral_constant>; #else // _LIBCPP_STD_VER < 20 diff --git a/libcxx/include/__iterator/insert_iterator.h b/libcxx/include/__iterator/insert_iterator.h index b3311042014f8..e0ee0ce035e2a 100644 --- a/libcxx/include/__iterator/insert_iterator.h +++ b/libcxx/include/__iterator/insert_iterator.h @@ -29,10 +29,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -using __insert_iterator_iter_t = ranges::iterator_t<_Container>; +using __insert_iterator_iter_t _LIBCPP_NODEBUG = ranges::iterator_t<_Container>; #else template -using __insert_iterator_iter_t = typename _Container::iterator; +using __insert_iterator_iter_t _LIBCPP_NODEBUG = typename _Container::iterator; #endif _LIBCPP_SUPPRESS_DEPRECATED_PUSH diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index eb6ba8b62fb30..db68dd2c377ac 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -47,7 +47,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -using __with_reference = _Tp&; +using __with_reference _LIBCPP_NODEBUG = _Tp&; template concept __can_reference = requires { typename __with_reference<_Tp>; }; @@ -80,19 +80,20 @@ struct __iter_traits_cache { using type = _If< __is_primary_template >::value, _Iter, iterator_traits<_Iter> >; }; template -using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; +using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type; struct __iter_concept_concept_test { template - using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept; }; struct __iter_concept_category_test { template - using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category; }; struct __iter_concept_random_fallback { template - using _Apply = __enable_if_t< __is_primary_template >::value, random_access_iterator_tag >; + using _Apply _LIBCPP_NODEBUG = + __enable_if_t<__is_primary_template >::value, random_access_iterator_tag>; }; template @@ -106,7 +107,7 @@ struct __iter_concept_cache { }; template -using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; +using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; template struct __has_iterator_typedefs { @@ -364,7 +365,7 @@ struct __iterator_traits<_Ip> { template struct iterator_traits : __iterator_traits<_Ip> { - using __primary_template = iterator_traits; + using __primary_template _LIBCPP_NODEBUG = iterator_traits; }; #else // _LIBCPP_STD_VER >= 20 @@ -397,7 +398,7 @@ struct __iterator_traits<_Iter, true> template struct _LIBCPP_TEMPLATE_VIS iterator_traits : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { - using __primary_template = iterator_traits; + using __primary_template _LIBCPP_NODEBUG = iterator_traits; }; #endif // _LIBCPP_STD_VER >= 20 @@ -430,16 +431,19 @@ template struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; template -using __has_input_iterator_category = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; +using __has_input_iterator_category _LIBCPP_NODEBUG = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; template -using __has_forward_iterator_category = __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; +using __has_forward_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; template -using __has_bidirectional_iterator_category = __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; +using __has_bidirectional_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; template -using __has_random_access_iterator_category = __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; +using __has_random_access_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; // __libcpp_is_contiguous_iterator determines if an iterator is known by // libc++ to be contiguous, either because it advertises itself as such @@ -466,48 +470,49 @@ template class __wrap_iter; template -using __has_exactly_input_iterator_category = +using __has_exactly_input_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value>; template -using __has_exactly_forward_iterator_category = +using __has_exactly_forward_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value>; template -using __has_exactly_bidirectional_iterator_category = +using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value>; template -using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; +using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type; template -using __iter_key_type = __remove_const_t::value_type::first_type>; +using __iter_key_type _LIBCPP_NODEBUG = + __remove_const_t::value_type::first_type>; template -using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; +using __iter_mapped_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type::second_type; template -using __iter_to_alloc_type = +using __iter_to_alloc_type _LIBCPP_NODEBUG = pair::value_type::first_type, typename iterator_traits<_InputIterator>::value_type::second_type>; template -using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category; +using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; template -using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; +using __iterator_pointer_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::pointer; template -using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; +using __iter_diff_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type; template -using __iter_reference = typename iterator_traits<_Iter>::reference; +using __iter_reference _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::reference; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__iterator/projected.h b/libcxx/include/__iterator/projected.h index 1c560ec055001..d12f0167de1df 100644 --- a/libcxx/include/__iterator/projected.h +++ b/libcxx/include/__iterator/projected.h @@ -26,9 +26,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __projected_impl { struct __type { - using __primary_template = __type; - using __projected_iterator = _It; - using __projected_projection = _Proj; + using __primary_template _LIBCPP_NODEBUG = __type; + using __projected_iterator _LIBCPP_NODEBUG = _It; + using __projected_projection _LIBCPP_NODEBUG = _Proj; using value_type = remove_cvref_t>; indirect_result_t<_Proj&, _It> operator*() const; // not defined @@ -38,9 +38,9 @@ struct __projected_impl { template struct __projected_impl<_It, _Proj> { struct __type { - using __primary_template = __type; - using __projected_iterator = _It; - using __projected_projection = _Proj; + using __primary_template _LIBCPP_NODEBUG = __type; + using __projected_iterator _LIBCPP_NODEBUG = _It; + using __projected_projection _LIBCPP_NODEBUG = _Proj; using value_type = remove_cvref_t>; using difference_type = iter_difference_t<_It>; diff --git a/libcxx/include/__iterator/ranges_iterator_traits.h b/libcxx/include/__iterator/ranges_iterator_traits.h index 859e7082048ac..9a31b651eb5da 100644 --- a/libcxx/include/__iterator/ranges_iterator_traits.h +++ b/libcxx/include/__iterator/ranges_iterator_traits.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template -using __range_key_type = __remove_const_t::first_type>; +using __range_key_type _LIBCPP_NODEBUG = __remove_const_t::first_type>; template -using __range_mapped_type = typename ranges::range_value_t<_Range>::second_type; +using __range_mapped_type _LIBCPP_NODEBUG = typename ranges::range_value_t<_Range>::second_type; template -using __range_to_alloc_type = +using __range_to_alloc_type _LIBCPP_NODEBUG = pair::first_type, typename ranges::range_value_t<_Range>::second_type>; #endif diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index 5e88d86ad5e9b..5bd1f868d3ff3 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -329,8 +329,8 @@ __reverse_range(_Range&& __range) { template struct __unwrap_iter_impl >, __b> { - using _UnwrappedIter = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); - using _ReverseWrapper = reverse_iterator >; + using _UnwrappedIter _LIBCPP_NODEBUG = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); + using _ReverseWrapper _LIBCPP_NODEBUG = reverse_iterator >; static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ReverseWrapper __rewrap(_ReverseWrapper __orig_iter, _UnwrappedIter __unwrapped_iter) { diff --git a/libcxx/include/__iterator/segmented_iterator.h b/libcxx/include/__iterator/segmented_iterator.h index 8cb54a35a7f5e..7a8e1addeacd9 100644 --- a/libcxx/include/__iterator/segmented_iterator.h +++ b/libcxx/include/__iterator/segmented_iterator.h @@ -72,7 +72,7 @@ template struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {}; template -using __is_segmented_iterator = __has_specialization<__segmented_iterator_traits<_Iterator> >; +using __is_segmented_iterator _LIBCPP_NODEBUG = __has_specialization<__segmented_iterator_traits<_Iterator> >; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__locale b/libcxx/include/__locale index b675e01bac81e..94dc8a08437bf 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -50,7 +50,7 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&); class _LIBCPP_EXPORTED_FROM_ABI locale { public: // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor. - using __trivially_relocatable = locale; + using __trivially_relocatable _LIBCPP_NODEBUG = locale; // types: class _LIBCPP_EXPORTED_FROM_ABI facet; diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h index c8097beb9052d..9957429c1e7c2 100644 --- a/libcxx/include/__locale_dir/locale_base_api.h +++ b/libcxx/include/__locale_dir/locale_base_api.h @@ -135,7 +135,7 @@ namespace __locale { // // Locale management // -using __locale_t = locale_t; +using __locale_t _LIBCPP_NODEBUG = locale_t; inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) { return newlocale(__category_mask, __name, __loc); diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h index edbc30a7a40e4..65a697769bdaa 100644 --- a/libcxx/include/__mdspan/extents.h +++ b/libcxx/include/__mdspan/extents.h @@ -129,14 +129,14 @@ struct __maybe_static_array { // Static values member static constexpr size_t __size_ = sizeof...(_Values); static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0); - using _StaticValues = __static_array<_TStatic, _Values...>; - using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>; + using _StaticValues _LIBCPP_NODEBUG = __static_array<_TStatic, _Values...>; + using _DynamicValues _LIBCPP_NODEBUG = __possibly_empty_array<_TDynamic, __size_dynamic_>; // Dynamic values member _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_; // static mapping of indices to the position in the dynamic values array - using _DynamicIdxMap = __static_partial_sums(_Values == _DynTag)...>; + using _DynamicIdxMap _LIBCPP_NODEBUG = __static_partial_sums(_Values == _DynTag)...>; template _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept { @@ -292,7 +292,8 @@ class extents { static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0); // internal storage type using __maybe_static_array - using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; + using _Values _LIBCPP_NODEBUG = + __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; [[no_unique_address]] _Values __vals_; public: diff --git a/libcxx/include/__memory/allocation_guard.h b/libcxx/include/__memory/allocation_guard.h index 66d6a5002c299..66edcd92ed618 100644 --- a/libcxx/include/__memory/allocation_guard.h +++ b/libcxx/include/__memory/allocation_guard.h @@ -45,8 +45,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // custom allocator. template struct __allocation_guard { - using _Pointer = typename allocator_traits<_Alloc>::pointer; - using _Size = typename allocator_traits<_Alloc>::size_type; + using _Pointer _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::pointer; + using _Size _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::size_type; template // we perform the allocator conversion inside the constructor _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index e35cfb7c3b878..afe3d1bf8a2de 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -176,10 +176,10 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> { #ifndef _LIBCPP_CXX03_LANG template -using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; +using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>; #else template -using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; +using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>::other; #endif // to_address @@ -276,7 +276,7 @@ struct __pointer_of<_Tp> { }; template -using __pointer_of_t = typename __pointer_of<_Tp>::type; +using __pointer_of_t _LIBCPP_NODEBUG = typename __pointer_of<_Tp>::type; template struct __pointer_of_or { @@ -290,7 +290,7 @@ struct __pointer_of_or<_Tp, _Up> { }; template -using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type; +using __pointer_of_or_t _LIBCPP_NODEBUG = typename __pointer_of_or<_Tp, _Up>::type; template concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); }; diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 97e4031499ed5..06b1fc488cf51 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -141,7 +141,7 @@ struct __for_overwrite_tag {}; template struct __shared_ptr_emplace : __shared_weak_count { - using __value_type = __remove_cv_t<_Tp>; + using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>; template -using __shared_ptr_nullptr_deleter_ctor_reqs = _And, __well_formed_deleter<_Dp, nullptr_t> >; +using __shared_ptr_nullptr_deleter_ctor_reqs _LIBCPP_NODEBUG = + _And, __well_formed_deleter<_Dp, nullptr_t> >; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) @@ -315,7 +316,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { // A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require // any bookkeeping, so it's always trivially relocatable. - using __trivially_relocatable = shared_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = shared_ptr; private: element_type* __ptr_; @@ -1210,7 +1211,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { // A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require // any bookkeeping, so it's always trivially relocatable. - using __trivially_relocatable = weak_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = weak_ptr; private: element_type* __ptr_; diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 2368f7b03e005..29d391fc80fe4 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -153,7 +153,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { // // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no // references to itself. This means that the entire structure is trivially relocatable if its members are. - using __trivially_relocatable = __conditional_t< + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t< __libcpp_is_trivially_relocatable::value && __libcpp_is_trivially_relocatable::value, unique_ptr, void>; @@ -189,7 +189,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) >; template - using _EnableIfDeleterAssignable = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >; + using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >; public: template > @@ -419,7 +419,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> // // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no // references to itself. This means that the entire structure is trivially relocatable if its members are. - using __trivially_relocatable = __conditional_t< + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t< __libcpp_is_trivially_relocatable::value && __libcpp_is_trivially_relocatable::value, unique_ptr, void>; @@ -430,9 +430,9 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_); #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR - using _BoundsChecker = __unique_ptr_array_bounds_stored; + using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stored; #else - using _BoundsChecker = __unique_ptr_array_bounds_stateless; + using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stateless; #endif _LIBCPP_NO_UNIQUE_ADDRESS _BoundsChecker __checker_; diff --git a/libcxx/include/__memory/unique_temporary_buffer.h b/libcxx/include/__memory/unique_temporary_buffer.h index ca6292338c005..dea7fa8e18728 100644 --- a/libcxx/include/__memory/unique_temporary_buffer.h +++ b/libcxx/include/__memory/unique_temporary_buffer.h @@ -45,7 +45,7 @@ struct __temporary_buffer_deleter { }; template -using __unique_temporary_buffer = unique_ptr<_Tp, __temporary_buffer_deleter<_Tp> >; +using __unique_temporary_buffer _LIBCPP_NODEBUG = unique_ptr<_Tp, __temporary_buffer_deleter<_Tp> >; template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_CONSTEXPR_SINCE_CXX23 __unique_temporary_buffer<_Tp> diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index d0b35bfd19340..8f32f2de83391 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -188,10 +188,10 @@ struct __map_node_handle_specifics { }; template -using __set_node_handle = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; +using __set_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; template -using __map_node_handle = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; +using __map_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; template struct _LIBCPP_TEMPLATE_VIS __insert_return_type { diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h index 2132e8dbceb3a..a7d53b6a1c989 100644 --- a/libcxx/include/__pstl/backend_fwd.h +++ b/libcxx/include/__pstl/backend_fwd.h @@ -53,11 +53,13 @@ struct __serial_backend_tag; struct __std_thread_backend_tag; # if defined(_LIBCPP_PSTL_BACKEND_SERIAL) -using __current_configuration = __backend_configuration<__serial_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = __backend_configuration<__serial_backend_tag, __default_backend_tag>; # elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) -using __current_configuration = __backend_configuration<__std_thread_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = + __backend_configuration<__std_thread_backend_tag, __default_backend_tag>; # elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) -using __current_configuration = __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = + __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>; # else // ...New vendors can add parallel backends here... diff --git a/libcxx/include/__pstl/dispatch.h b/libcxx/include/__pstl/dispatch.h index ea40fa79eb949..828842368e339 100644 --- a/libcxx/include/__pstl/dispatch.h +++ b/libcxx/include/__pstl/dispatch.h @@ -58,7 +58,8 @@ struct __find_first_implemented<_Algorithm, __backend_configuration<_B1, _Bn...> __find_first_implemented<_Algorithm, __backend_configuration<_Bn...>, _ExecutionPolicy> > {}; template